From d70ccebc8cf76dadb81ab8d253bec9ef1f4951a1 Mon Sep 17 00:00:00 2001 From: Pablo Carranza Velez Date: Tue, 20 Feb 2024 10:57:24 -0300 Subject: [PATCH 001/277] chore: add first draft IHorizonStaking --- .../contracts/staking/IHorizonStaking.sol | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 packages/contracts/contracts/staking/IHorizonStaking.sol diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol new file mode 100644 index 000000000..92ebe7a33 --- /dev/null +++ b/packages/contracts/contracts/staking/IHorizonStaking.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.7.6; +pragma abicoder v2; + +interface IHorizonStaking { + struct Provision { + // Service provider that created the provision + address serviceProvider; + // tokens in the provision + uint256 tokens; + // tokens that are being thawed (and will stop being slashable soon) + uint256 tokensThawing; + // timestamp of provision creation + uint64 createdAt; + // authority to slash the provision + address verifier; + // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed + uint32 maxVerifierCut; + // time, in seconds, tokens must thaw before being withdrawn + uint64 thawingPeriod; + } + + // the new "Indexer" struct + struct ServiceProviderInternal { + // Tokens on the Service Provider stake (staked by the provider) + uint256 tokensStaked; + // Tokens used in allocations + uint256 __DEPRECATED_tokensAllocated; + // Tokens locked for withdrawal subject to thawing period + uint256 __DEPRECATED_tokensLocked; + // Block when locked tokens can be withdrawn + uint256 __DEPRECATED_tokensLockedUntil; + // tokens used in a provision + uint256 tokensProvisioned; + // tokens that initiated a thawing in any one of the provider's provisions + uint256 tokensRequestedThaw; + // tokens that have been removed from any one of the provider's provisions after thawing + uint256 tokensFulfilledThaw; + // provisions that take priority for undelegation force thawing + bytes32[] forceThawProvisions; + } + + struct ServiceProvider { + // Tokens on the provider stake (staked by the provider) + uint256 tokensStaked; + // tokens used in a provision + uint256 tokensProvisioned; + // tokens that initiated a thawing in any one of the provider's provisions + uint256 tokensRequestedThaw; + // tokens that have been removed from any one of the provider's provisions after thawing + uint256 tokensFulfilledThaw; + // provisions that take priority for undelegation force thawing + bytes32[] forceThawProvisions; + } + + struct DelegationPool { + uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase + uint32 __DEPRECATED_indexingRewardCut; // in PPM + uint32 __DEPRECATED_queryFeeCut; // in PPM + uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated + uint256 tokens; // Total tokens as pool reserves + uint256 shares; // Total shares minted in the pool + mapping(address => Delegation) delegators; // Mapping of delegator => Delegation + } + + struct Delegation { + // shares owned by the delegator in the pool + uint256 shares; + // tokens delegated to the pool + uint256 tokens; + // Timestamp when locked tokens can be undelegated (after the timelock) + uint256 tokensLockedUntil; + } + + struct ThawRequest { + // tokens that are being thawed by this request + uint256 tokens; + // the provision id to which this request corresponds to + bytes32 provisionId; + // the address that initiated the thaw request, allowed to remove the funds once thawed + address owner; + // the timestamp when the thawed funds can be removed from the provision + uint64 thawingUntil; + // the value of `ServiceProvider.tokensRequestedThaw` the moment the thaw request is created + uint256 tokensRequestedThawSnapshot; + } + + // whitelist/deny a verifier + function allowVerifier(address verifier, bool allow) external; + + // deposit stake + function stake(uint256 tokens) external; + + // create a provision + function provision( + uint256 tokens, + address verifier, + uint256 maxVerifierCut, + uint256 thawingPeriod + ) external; + + // initiate a thawing to remove tokens from a provision + function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32); + + // moves thawed stake from a provision back into the provider's available stake + function deprovision(bytes32 thawRequestId) external; + + // moves thawed stake from one provision into another provision + function reprovision(bytes32 thawRequestId, bytes32 provisionId) external; + + // moves thawed stake back to the owner's account - stake is removed from the protocol + function withdraw(bytes32 thawRequestId) external; + + // delegate tokens to a provider + function delegate(address serviceProvider, uint256 tokens) external; + + // undelegate tokens + function undelegate( + address serviceProvider, + uint256 tokens, + bytes32[] provisions + ) external returns (bytes32[]); + + // slash a service provider + function slash( + bytes32 provisionId, + uint256 tokens, + uint256 verifierAmount + ) external; + + // set the Service Provider's preferred provisions to be force thawed + function setForceThawProvisions(bytes32[] provisions); + + // total staked tokens to the provider + // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` + function getStake(address serviceProvider) public view returns (uint256 tokens); + + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address serviceProvider) public view returns (uint256 tokens); + + // staked tokens the provider can provision before hitting the delegation cap + // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` + function getCapacity(address serviceProvider) public view returns (uint256); + + // provisioned tokens that are not being used + // `Provision.tokens - Provision.tokensThawing` + function getTokensAvailable(bytes32 provision) public view returns (uint256 tokens); + + function getServiceProvider(address serviceProvider) + public + view + returns (ServiceProvider memory); + + function getProvision(bytes32 provision) public view returns (Provision memory); +} From 7d096e164788acf5e236201743e172c562371abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 21 Feb 2024 17:52:32 -0300 Subject: [PATCH 002/277] fix: horizon staking interface compilation errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/staking/IHorizonStaking.sol | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol index 92ebe7a33..51cb03c33 100644 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ b/packages/contracts/contracts/staking/IHorizonStaking.sol @@ -101,7 +101,7 @@ interface IHorizonStaking { ) external; // initiate a thawing to remove tokens from a provision - function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32); + function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId); // moves thawed stake from a provision back into the provider's available stake function deprovision(bytes32 thawRequestId) external; @@ -119,8 +119,8 @@ interface IHorizonStaking { function undelegate( address serviceProvider, uint256 tokens, - bytes32[] provisions - ) external returns (bytes32[]); + bytes32[] calldata provisions + ) external returns (bytes32 thawRequestId); // slash a service provider function slash( @@ -130,28 +130,28 @@ interface IHorizonStaking { ) external; // set the Service Provider's preferred provisions to be force thawed - function setForceThawProvisions(bytes32[] provisions); + function setForceThawProvisions(bytes32[] calldata provisions) external; // total staked tokens to the provider // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` - function getStake(address serviceProvider) public view returns (uint256 tokens); + function getStake(address serviceProvider) external view returns (uint256 tokens); // staked tokens that are currently not provisioned, aka idle stake // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) public view returns (uint256 tokens); + function getIdleStake(address serviceProvider) external view returns (uint256 tokens); // staked tokens the provider can provision before hitting the delegation cap // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` - function getCapacity(address serviceProvider) public view returns (uint256); + function getCapacity(address serviceProvider) external view returns (uint256 tokens); // provisioned tokens that are not being used // `Provision.tokens - Provision.tokensThawing` - function getTokensAvailable(bytes32 provision) public view returns (uint256 tokens); + function getTokensAvailable(bytes32 provision) external view returns (uint256 tokens); function getServiceProvider(address serviceProvider) - public + external view returns (ServiceProvider memory); - function getProvision(bytes32 provision) public view returns (Provision memory); + function getProvision(bytes32 provision) external view returns (Provision memory); } From a4e6c2653ec579d1c013ae260c6bf0a02adfd0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 14 Mar 2024 14:51:01 -0300 Subject: [PATCH 003/277] chore: bump contracts package version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .github/workflows/ci-token-dist.yml | 4 ++- packages/contracts/CHANGELOG.md | 6 ++++ .../contracts/contracts/arbitrum/Arbitrum.md | 5 +++ packages/contracts/package.json | 6 ++-- packages/contracts/scripts/build | 12 ++++++- packages/contracts/scripts/prepack | 20 ----------- packages/contracts/scripts/test | 1 - packages/sdk/CHANGELOG.md | 6 ++++ packages/sdk/package.json | 4 +-- packages/token-distribution/CHANGELOG.md | 7 ++++ packages/token-distribution/package.json | 6 ++-- yarn.lock | 36 ++++++++++++++----- 12 files changed, 74 insertions(+), 39 deletions(-) create mode 100644 packages/contracts/contracts/arbitrum/Arbitrum.md delete mode 100755 packages/contracts/scripts/prepack create mode 100644 packages/token-distribution/CHANGELOG.md diff --git a/.github/workflows/ci-token-dist.yml b/.github/workflows/ci-token-dist.yml index 76922ff9d..7b0bd8767 100644 --- a/.github/workflows/ci-token-dist.yml +++ b/.github/workflows/ci-token-dist.yml @@ -23,4 +23,6 @@ jobs: - name: Set up environment uses: ./.github/actions/setup - name: Run tests - run: yarn test \ No newline at end of file + run: | + pushd packages/token-distribution + yarn test \ No newline at end of file diff --git a/packages/contracts/CHANGELOG.md b/packages/contracts/CHANGELOG.md index 802cff94c..cdbb2c892 100644 --- a/packages/contracts/CHANGELOG.md +++ b/packages/contracts/CHANGELOG.md @@ -1,5 +1,11 @@ # @graphprotocol/contracts +## 7.0.0 + +### Major Changes + +- 9686ce1: Add Horizon staking interface + ## 6.2.1 ### Patch Changes diff --git a/packages/contracts/contracts/arbitrum/Arbitrum.md b/packages/contracts/contracts/arbitrum/Arbitrum.md new file mode 100644 index 000000000..abc87553e --- /dev/null +++ b/packages/contracts/contracts/arbitrum/Arbitrum.md @@ -0,0 +1,5 @@ +# Arbitrum contracts + +These contracts have been copied from the [Arbitrum repo](https://github.com/OffchainLabs/arbitrum). + +They are also available as part of the npm packages [arb-bridge-eth](https://www.npmjs.com/package/arb-bridge-eth) and [arb-bridge-peripherals](https://www.npmjs.com/package/arb-bridge-peripherals). The reason for copying them rather than installing those packages is the contracts only support Solidity `^0.6.11`, so we had to change the version to `^0.7.6` for it to be compatible with our other contracts. diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 4e95a8f3c..6dea50dad 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@graphprotocol/contracts", - "version": "6.2.1", + "version": "7.0.0", "description": "Contracts for the Graph Protocol", "directories": { "test": "test" @@ -75,13 +75,13 @@ "solidity-coverage": "^0.7.16", "ts-node": "^10.9.1", "typechain": "^5.0.0", - "typescript": "^4.7.4", + "typescript": "^5.2.2", "winston": "^3.3.3", "yaml": "^1.10.2", "yargs": "^17.0.0" }, "scripts": { - "prepack": "scripts/prepack", + "prepack": "SKIP_LOAD=true scripts/build", "build": "SKIP_LOAD=true scripts/build", "clean": "rm -rf build/ cache/ dist/", "compile": "hardhat compile", diff --git a/packages/contracts/scripts/build b/packages/contracts/scripts/build index df72b9f62..e330635ba 100755 --- a/packages/contracts/scripts/build +++ b/packages/contracts/scripts/build @@ -1,6 +1,16 @@ #!/bin/bash +TYPECHAIN_DIR=dist/types + set -eo pipefail -# Build +# Build contracts +yarn clean yarn compile + +# Refresh distribution folder +rm -rf dist && mkdir -p ${TYPECHAIN_DIR} +cp -R build/abis/ dist/abis +cp -R build/types/ ${TYPECHAIN_DIR} + +tsc --esModuleInterop \ No newline at end of file diff --git a/packages/contracts/scripts/prepack b/packages/contracts/scripts/prepack deleted file mode 100755 index bc0e54391..000000000 --- a/packages/contracts/scripts/prepack +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -TYPECHAIN_DIR=dist/types - -set -eo pipefail -set +o noglob - -# Build contracts -yarn clean -yarn build - -# Refresh distribution folder -rm -rf dist && mkdir -p ${TYPECHAIN_DIR} -cp -R build/abis/ dist/abis -cp -R build/types/ ${TYPECHAIN_DIR} - -# Build and create TS declarations -pushd ${TYPECHAIN_DIR} -ls *.ts **/*.ts | xargs tsc --esModuleInterop -popd diff --git a/packages/contracts/scripts/test b/packages/contracts/scripts/test index 376090d90..4156166ae 100755 --- a/packages/contracts/scripts/test +++ b/packages/contracts/scripts/test @@ -6,7 +6,6 @@ source $(pwd)/scripts/evm ### Setup EVM # Ensure we compiled sources - yarn build ### Cleanup diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md index 20a787d51..9cc5a8e17 100644 --- a/packages/sdk/CHANGELOG.md +++ b/packages/sdk/CHANGELOG.md @@ -1,5 +1,11 @@ # @graphprotocol/sdk +## 0.5.1 + +### Patch Changes + +- Bump contracts dependency + ## 0.5.0 ### Minor Changes diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 18497431e..6083abdcb 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@graphprotocol/sdk", - "version": "0.5.0", + "version": "0.5.1", "description": "TypeScript based SDK to interact with The Graph protocol contracts", "main": "build/index.js", "types": "src/index.ts", @@ -21,7 +21,7 @@ "@arbitrum/sdk": "~3.1.13", "@ethersproject/experimental": "^5.7.0", "@graphprotocol/common-ts": "^2.0.7", - "@graphprotocol/contracts": "workspace:^6.2.0", + "@graphprotocol/contracts": "workspace:^7.0.0", "@nomicfoundation/hardhat-network-helpers": "^1.0.9", "@nomiclabs/hardhat-ethers": "^2.2.3", "debug": "^4.3.4", diff --git a/packages/token-distribution/CHANGELOG.md b/packages/token-distribution/CHANGELOG.md new file mode 100644 index 000000000..2809305b6 --- /dev/null +++ b/packages/token-distribution/CHANGELOG.md @@ -0,0 +1,7 @@ +# @graphprotocol/token-distribution + +## 1.2.1 + +### Patch Changes + +- Bump contracts dependency diff --git a/packages/token-distribution/package.json b/packages/token-distribution/package.json index 37069fc41..097bc13e0 100644 --- a/packages/token-distribution/package.json +++ b/packages/token-distribution/package.json @@ -1,6 +1,6 @@ { "name": "@graphprotocol/token-distribution", - "version": "1.2.0", + "version": "1.2.1", "description": "Graph Token Distribution", "main": "index.js", "scripts": { @@ -31,7 +31,7 @@ "devDependencies": { "@ethersproject/experimental": "^5.0.7", "@graphprotocol/client-cli": "^2.0.2", - "@graphprotocol/contracts": "^5.0.0", + "@graphprotocol/contracts": "workspace:^7.0.0", "@nomiclabs/hardhat-ethers": "^2.0.0", "@nomiclabs/hardhat-etherscan": "^3.1.7", "@nomiclabs/hardhat-waffle": "^2.0.0", @@ -65,6 +65,6 @@ "solhint-plugin-prettier": "^0.1.0", "ts-node": "^10.9.1", "typechain": "^5.0.0", - "typescript": "^4.0.2" + "typescript": "^5.2.2" } } diff --git a/yarn.lock b/yarn.lock index 1ed3feab6..820ba1b2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2795,7 +2795,7 @@ __metadata: languageName: node linkType: hard -"@graphprotocol/contracts@npm:5.3.3, @graphprotocol/contracts@npm:^5.0.0": +"@graphprotocol/contracts@npm:5.3.3": version: 5.3.3 resolution: "@graphprotocol/contracts@npm:5.3.3" dependencies: @@ -2805,7 +2805,7 @@ __metadata: languageName: node linkType: hard -"@graphprotocol/contracts@workspace:^6.2.0, @graphprotocol/contracts@workspace:packages/contracts": +"@graphprotocol/contracts@workspace:^7.0.0, @graphprotocol/contracts@workspace:packages/contracts": version: 0.0.0-use.local resolution: "@graphprotocol/contracts@workspace:packages/contracts" dependencies: @@ -2869,7 +2869,7 @@ __metadata: solidity-coverage: "npm:^0.7.16" ts-node: "npm:^10.9.1" typechain: "npm:^5.0.0" - typescript: "npm:^4.7.4" + typescript: "npm:^5.2.2" winston: "npm:^3.3.3" yaml: "npm:^1.10.2" yargs: "npm:^17.0.0" @@ -2936,7 +2936,7 @@ __metadata: "@arbitrum/sdk": "npm:~3.1.13" "@ethersproject/experimental": "npm:^5.7.0" "@graphprotocol/common-ts": "npm:^2.0.7" - "@graphprotocol/contracts": "workspace:^6.2.0" + "@graphprotocol/contracts": "workspace:^7.0.0" "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.9" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@types/chai": "npm:^4.3.9" @@ -2973,7 +2973,7 @@ __metadata: dependencies: "@ethersproject/experimental": "npm:^5.0.7" "@graphprotocol/client-cli": "npm:^2.0.2" - "@graphprotocol/contracts": "npm:^5.0.0" + "@graphprotocol/contracts": "workspace:^7.0.0" "@nomiclabs/hardhat-ethers": "npm:^2.0.0" "@nomiclabs/hardhat-etherscan": "npm:^3.1.7" "@nomiclabs/hardhat-waffle": "npm:^2.0.0" @@ -3007,7 +3007,7 @@ __metadata: solhint-plugin-prettier: "npm:^0.1.0" ts-node: "npm:^10.9.1" typechain: "npm:^5.0.0" - typescript: "npm:^4.0.2" + typescript: "npm:^5.2.2" languageName: unknown linkType: soft @@ -23171,7 +23171,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.0.2, typescript@npm:^4.4.3, typescript@npm:^4.7.4": +"typescript@npm:^4.0.2, typescript@npm:^4.4.3": version: 4.9.5 resolution: "typescript@npm:4.9.5" bin: @@ -23191,7 +23191,17 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^4.0.2#optional!builtin, typescript@patch:typescript@npm%3A^4.4.3#optional!builtin, typescript@patch:typescript@npm%3A^4.7.4#optional!builtin": +"typescript@npm:^5.2.2": + version: 5.4.2 + resolution: "typescript@npm:5.4.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 583ff68cafb0c076695f72d61df6feee71689568179fb0d3a4834dac343df6b6ed7cf7b6f6c801fa52d43cd1d324e2f2d8ae4497b09f9e6cfe3d80a6d6c9ca52 + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A^4.0.2#optional!builtin, typescript@patch:typescript@npm%3A^4.4.3#optional!builtin": version: 4.9.5 resolution: "typescript@patch:typescript@npm%3A4.9.5#optional!builtin::version=4.9.5&hash=289587" bin: @@ -23211,6 +23221,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.2.2#optional!builtin": + version: 5.4.2 + resolution: "typescript@patch:typescript@npm%3A5.4.2#optional!builtin::version=5.4.2&hash=e012d7" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 22e2f213c3ffe5960c5eaec6c95c04e01858fed57a94be250746f540b935b2c18c3c3fc80d3ab65d28c0aba1eb76284557ba3bf521d28caee811c44ba2b648f9 + languageName: node + linkType: hard + "typewise-core@npm:^1.2, typewise-core@npm:^1.2.0": version: 1.2.0 resolution: "typewise-core@npm:1.2.0" From 0e8895b49ed3facc0cce34ddd29b609f2f94bc7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 21 Mar 2024 17:47:22 -0300 Subject: [PATCH 004/277] fix(contracts): build type code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/contracts/package.json | 1 + packages/contracts/scripts/build | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 6dea50dad..e3f8b71c8 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -5,6 +5,7 @@ "directories": { "test": "test" }, + "main": "dist/types/index.js", "types": "build/types/index.d.ts", "files": [ "dist/**/*", diff --git a/packages/contracts/scripts/build b/packages/contracts/scripts/build index e330635ba..06b9823c1 100755 --- a/packages/contracts/scripts/build +++ b/packages/contracts/scripts/build @@ -7,10 +7,11 @@ set -eo pipefail # Build contracts yarn clean yarn compile +tsc -# Refresh distribution folder -rm -rf dist && mkdir -p ${TYPECHAIN_DIR} +# Copy types and abis to distribution folder +cp -R build/types/* dist/build/types cp -R build/abis/ dist/abis -cp -R build/types/ ${TYPECHAIN_DIR} -tsc --esModuleInterop \ No newline at end of file +# Move compiled types ts +mv dist/build/types dist/types \ No newline at end of file From 258549551f8b5486391819c79070749d841d4734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 8 Apr 2024 14:04:09 -0300 Subject: [PATCH 005/277] chore(horizon): add horizon package boilerplate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .github/actions/setup/action.yml | 2 + .github/workflows/build.yml | 2 + .github/workflows/ci-contracts.yml | 2 + .github/workflows/ci-horizon.yml | 30 + .github/workflows/ci-token-dist.yml | 2 + .github/workflows/e2e-contracts.yml | 2 + .github/workflows/publish.yml | 2 + .github/workflows/verifydeployed.yml | 2 + .gitignore | 6 +- .gitmodules | 3 + .husky/pre-commit | 7 +- README.md | 3 +- package.json | 1 + .../contracts/staking/IHorizonStaking.sol | 24 +- packages/horizon/README.md | 13 + packages/horizon/contracts/SimpleTest.sol | 10 + packages/horizon/eslint.config.js | 21 + packages/horizon/foundry.toml | 6 + packages/horizon/hardhat.config.ts | 13 + packages/horizon/lib/forge-std | 1 + packages/horizon/package.json | 58 ++ packages/horizon/prettier.config.js | 2 + packages/horizon/remappings.txt | 5 + packages/horizon/scripts/deploy.ts | 28 + packages/horizon/test/SimpleTest.t.sol | 17 + packages/horizon/test/SimpleTest.ts | 23 + packages/horizon/tsconfig.json | 18 + yarn.lock | 805 +++++++++++++++++- 28 files changed, 1057 insertions(+), 51 deletions(-) create mode 100644 .github/workflows/ci-horizon.yml create mode 100644 .gitmodules create mode 100644 packages/horizon/README.md create mode 100644 packages/horizon/contracts/SimpleTest.sol create mode 100644 packages/horizon/eslint.config.js create mode 100644 packages/horizon/foundry.toml create mode 100644 packages/horizon/hardhat.config.ts create mode 160000 packages/horizon/lib/forge-std create mode 100644 packages/horizon/package.json create mode 100644 packages/horizon/prettier.config.js create mode 100644 packages/horizon/remappings.txt create mode 100644 packages/horizon/scripts/deploy.ts create mode 100644 packages/horizon/test/SimpleTest.t.sol create mode 100644 packages/horizon/test/SimpleTest.ts create mode 100644 packages/horizon/tsconfig.json diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index d6173e517..baeec7b27 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -4,6 +4,8 @@ runs: using: composite steps: + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 - name: Enable corepack for modern yarn shell: bash run: corepack enable diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 407b0e996..62e6408fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,5 +16,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up environment uses: ./.github/actions/setup \ No newline at end of file diff --git a/.github/workflows/ci-contracts.yml b/.github/workflows/ci-contracts.yml index 388bb8521..7dca1bfde 100644 --- a/.github/workflows/ci-contracts.yml +++ b/.github/workflows/ci-contracts.yml @@ -20,6 +20,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up environment uses: ./.github/actions/setup - name: Run tests diff --git a/.github/workflows/ci-horizon.yml b/.github/workflows/ci-horizon.yml new file mode 100644 index 000000000..d450d1264 --- /dev/null +++ b/.github/workflows/ci-horizon.yml @@ -0,0 +1,30 @@ +name: CI - packages/horizon + +env: + CI: true + +on: + push: + branches: "*" + paths: + - packages/horizon/** + pull_request: + branches: "*" + paths: + - packages/horizon/** + workflow_dispatch: + +jobs: + test-ci: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set up environment + uses: ./.github/actions/setup + - name: Run tests + run: | + pushd packages/horizon + yarn test \ No newline at end of file diff --git a/.github/workflows/ci-token-dist.yml b/.github/workflows/ci-token-dist.yml index 7b0bd8767..f45eb9111 100644 --- a/.github/workflows/ci-token-dist.yml +++ b/.github/workflows/ci-token-dist.yml @@ -20,6 +20,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up environment uses: ./.github/actions/setup - name: Run tests diff --git a/.github/workflows/e2e-contracts.yml b/.github/workflows/e2e-contracts.yml index 46a6387ca..c84adb1a0 100644 --- a/.github/workflows/e2e-contracts.yml +++ b/.github/workflows/e2e-contracts.yml @@ -30,6 +30,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up environment uses: ./.github/actions/setup - name: Run e2e tests diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dc01211d7..f942b6579 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,6 +23,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up environment uses: ./.github/actions/setup - name: Publish 🚀 diff --git a/.github/workflows/verifydeployed.yml b/.github/workflows/verifydeployed.yml index 549d6d7ed..9de43994c 100644 --- a/.github/workflows/verifydeployed.yml +++ b/.github/workflows/verifydeployed.yml @@ -25,6 +25,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + with: + submodules: recursive - name: Set up environment uses: ./.github/actions/setup diff --git a/.gitignore b/.gitignore index ecd5f0d2c..55602edb4 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ cached/ # Build artifacts dist/ build/ +typechain/ +typechain-types/ deployments/hardhat/ # Ignore solc bin output @@ -45,8 +47,10 @@ addresses-fork.json # Keys .keystore +# Forge artifacts +cache_forge # Graph client .graphclient tx-builder-*.json -!tx-builder-template.json \ No newline at end of file +!tx-builder-template.json diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..edd86d2b7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "packages/horizon/lib/forge-std"] + path = packages/horizon/lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/.husky/pre-commit b/.husky/pre-commit index 487427eda..92fa26604 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -9,4 +9,9 @@ popd # data-edge pushd packages/data-edge npx --no-install lint-staged -popd \ No newline at end of file +popd + +# graph horizon +pushd packages/horizon +npx --no-install lint-staged +popd diff --git a/README.md b/README.md index f9f736fb5..a36de65bf 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,10 @@ This repository is a Yarn workspaces monorepo containing the following 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. | | [eslint-graph-config](./packages/eslint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for TypeScript projects. | -| [token-distribution](./packages/token-distribution) | - | Contracts managing token locks for network participants | +| [horizon](./packages/horizon) | [![npm version]()]() | Contracts for Graph Horizon, the next iteration of The Graph protocol. | | [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 | | [solhint-graph-config](./packages/eslint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for Solidity projects. | +| [token-distribution](./packages/token-distribution) | - | Contracts managing token locks for network participants | ## Development diff --git a/package.json b/package.json index 4f1c06aa7..d27a50288 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "packages/contracts", "packages/data-edge", "packages/eslint-graph-config", + "packages/horizon", "packages/sdk", "packages/solhint-graph-config", "packages/token-distribution" diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol index 51cb03c33..a4101ff52 100644 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ b/packages/contracts/contracts/staking/IHorizonStaking.sol @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.7.6; +pragma solidity >=0.7.6 <0.9.0; pragma abicoder v2; +interface Test { + function test() external returns (uint256); +} + interface IHorizonStaking { struct Provision { // Service provider that created the provision @@ -93,12 +97,7 @@ interface IHorizonStaking { function stake(uint256 tokens) external; // create a provision - function provision( - uint256 tokens, - address verifier, - uint256 maxVerifierCut, - uint256 thawingPeriod - ) external; + function provision(uint256 tokens, address verifier, uint256 maxVerifierCut, uint256 thawingPeriod) external; // initiate a thawing to remove tokens from a provision function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId); @@ -123,11 +122,7 @@ interface IHorizonStaking { ) external returns (bytes32 thawRequestId); // slash a service provider - function slash( - bytes32 provisionId, - uint256 tokens, - uint256 verifierAmount - ) external; + function slash(bytes32 provisionId, uint256 tokens, uint256 verifierAmount) external; // set the Service Provider's preferred provisions to be force thawed function setForceThawProvisions(bytes32[] calldata provisions) external; @@ -148,10 +143,7 @@ interface IHorizonStaking { // `Provision.tokens - Provision.tokensThawing` function getTokensAvailable(bytes32 provision) external view returns (uint256 tokens); - function getServiceProvider(address serviceProvider) - external - view - returns (ServiceProvider memory); + function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); function getProvision(bytes32 provision) external view returns (Provision memory); } diff --git a/packages/horizon/README.md b/packages/horizon/README.md new file mode 100644 index 000000000..7be82e5d6 --- /dev/null +++ b/packages/horizon/README.md @@ -0,0 +1,13 @@ +# Sample Hardhat Project + +This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract. + +Try running some of the following tasks: + +```shell +npx hardhat help +npx hardhat test +REPORT_GAS=true npx hardhat test +npx hardhat node +npx hardhat run scripts/deploy.ts +``` diff --git a/packages/horizon/contracts/SimpleTest.sol b/packages/horizon/contracts/SimpleTest.sol new file mode 100644 index 000000000..5cc28d9cc --- /dev/null +++ b/packages/horizon/contracts/SimpleTest.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.4.0 <0.9.0; + +import { Test } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; + +contract SimpleTest is Test { + function test() external pure returns (uint256) { + return 42; + } +} diff --git a/packages/horizon/eslint.config.js b/packages/horizon/eslint.config.js new file mode 100644 index 000000000..2cb4335fd --- /dev/null +++ b/packages/horizon/eslint.config.js @@ -0,0 +1,21 @@ +// @ts-check +/* eslint-disable no-undef */ +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ + +const eslintGraphConfig = require('eslint-graph-config') +module.exports = [ + ...eslintGraphConfig.default, + { + rules: { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + }, + }, + { + ignores: ['typechain-types/*'], + }, +] diff --git a/packages/horizon/foundry.toml b/packages/horizon/foundry.toml new file mode 100644 index 000000000..55f7ffd31 --- /dev/null +++ b/packages/horizon/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = 'contracts' +out = 'build' +libs = ['node_modules', 'lib'] +test = 'test' +cache_path = 'cache_forge' \ No newline at end of file diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts new file mode 100644 index 000000000..f5c9172a8 --- /dev/null +++ b/packages/horizon/hardhat.config.ts @@ -0,0 +1,13 @@ +// import '@nomicfoundation/hardhat-foundry' +import '@nomicfoundation/hardhat-toolbox' +import { HardhatUserConfig } from 'hardhat/config' + +const config: HardhatUserConfig = { + solidity: '0.8.24', + paths: { + artifacts: './build/contracts', + sources: './contracts', + }, +} + +export default config diff --git a/packages/horizon/lib/forge-std b/packages/horizon/lib/forge-std new file mode 160000 index 000000000..bb4ceea94 --- /dev/null +++ b/packages/horizon/lib/forge-std @@ -0,0 +1 @@ +Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef diff --git a/packages/horizon/package.json b/packages/horizon/package.json new file mode 100644 index 000000000..ec23f62cb --- /dev/null +++ b/packages/horizon/package.json @@ -0,0 +1,58 @@ +{ + "name": "@graphprotocol/horizon", + "version": "0.0.1", + "description": "", + "author": "The Graph Team", + "license": "GPL-2.0-or-later", + "scripts": { + "lint:ts": "eslint '**/*.{js,ts}' --fix", + "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", + "lint": "yarn lint:ts && yarn lint:sol", + "clean": "rm -rf build cache typechain-types", + "build": "forge build && hardhat compile", + "test": "forge test && hardhat test" + }, + "devDependencies": { + "@graphprotocol/contracts": "workspace:^7.0.0", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-foundry": "^1.1.1", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-toolbox": "^4.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=16.0.0", + "chai": "^4.2.0", + "eslint": "^8.56.0", + "eslint-graph-config": "workspace:^0.0.1", + "ethers": "^6.4.0", + "hardhat": "^2.20.1", + "hardhat-gas-reporter": "^1.0.8", + "lint-staged": "^15.2.2", + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1", + "solhint": "^4.5.2", + "solhint-graph-config": "workspace:^0.0.1", + "solidity-coverage": "^0.8.0", + "ts-node": ">=8.0.0", + "typechain": "^8.3.0", + "typescript": "^5.3.3" + }, + "lint-staged": { + "contracts/**/*.sol": [ + "yarn lint:sol" + ], + "**/*.ts": [ + "yarn lint:ts" + ], + "**/*.js": [ + "yarn lint:ts" + ], + "**/*.json": [ + "yarn lint:ts" + ] + } +} diff --git a/packages/horizon/prettier.config.js b/packages/horizon/prettier.config.js new file mode 100644 index 000000000..5b8e866f2 --- /dev/null +++ b/packages/horizon/prettier.config.js @@ -0,0 +1,2 @@ +const prettierGraphConfig = require('solhint-graph-config/prettier') +module.exports = prettierGraphConfig diff --git a/packages/horizon/remappings.txt b/packages/horizon/remappings.txt new file mode 100644 index 000000000..1bd6482cd --- /dev/null +++ b/packages/horizon/remappings.txt @@ -0,0 +1,5 @@ +@graphprotocol/contracts/=node_modules/@graphprotocol/contracts/ +forge-std/=lib/forge-std/src/ +ds-test/=lib/forge-std/lib/ds-test/src/ +eth-gas-reporter/=node_modules/eth-gas-reporter/ +hardhat/=node_modules/hardhat/ diff --git a/packages/horizon/scripts/deploy.ts b/packages/horizon/scripts/deploy.ts new file mode 100644 index 000000000..cf87ff10f --- /dev/null +++ b/packages/horizon/scripts/deploy.ts @@ -0,0 +1,28 @@ +import { ethers } from 'hardhat' + +async function main() { + const currentTimestampInSeconds = Math.round(Date.now() / 1000) + const unlockTime = currentTimestampInSeconds + 60 + + const lockedAmount = ethers.parseEther('0.001') + const a = 1 + console.log(a) + const lock = await ethers.deployContract('Lock', [unlockTime], { + value: lockedAmount, + }) + + await lock.waitForDeployment() + + console.log( + `Lock with ${ethers.formatEther( + lockedAmount, + )}ETH and unlock timestamp ${unlockTime} deployed to ${typeof lock.target == 'string' ? lock.target : ''}`, + ) +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error) + process.exitCode = 1 +}) diff --git a/packages/horizon/test/SimpleTest.t.sol b/packages/horizon/test/SimpleTest.t.sol new file mode 100644 index 000000000..b130e5d34 --- /dev/null +++ b/packages/horizon/test/SimpleTest.t.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.10; + +import "forge-std/Test.sol"; +import { SimpleTest } from "../contracts/SimpleTest.sol"; + +contract ContractTest is Test { + SimpleTest simpleTest; + + function setUp() public { + simpleTest = new SimpleTest(); + } + + function test_NumberIs42() public { + assertEq(simpleTest.test(), 42); + } +} diff --git a/packages/horizon/test/SimpleTest.ts b/packages/horizon/test/SimpleTest.ts new file mode 100644 index 000000000..cfcfb1443 --- /dev/null +++ b/packages/horizon/test/SimpleTest.ts @@ -0,0 +1,23 @@ +import hardhat from 'hardhat' + +import { expect } from 'chai' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' + +const ethers = hardhat.ethers + +describe('SimpleTest', function () { + async function deployFixture() { + const [owner] = await ethers.getSigners() + const SimpleTest = await ethers.getContractFactory('SimpleTest') + const simpleTest = await SimpleTest.deploy() + return { simpleTest, owner } + } + + describe('Deployment', function () { + it('Should return 42', async function () { + const { simpleTest } = await loadFixture(deployFixture) + + expect(await simpleTest.test()).to.equal(42) + }) + }) +}) diff --git a/packages/horizon/tsconfig.json b/packages/horizon/tsconfig.json new file mode 100644 index 000000000..143316f16 --- /dev/null +++ b/packages/horizon/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": [ + "hardhat.config.ts", + "scripts/**/*.ts", + "test/**/*.ts", + "eslint.config.js", + "prettier.config.js" + ] +} diff --git a/yarn.lock b/yarn.lock index 820ba1b2a..27dfd84b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,6 +24,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:1.10.1": + version: 1.10.1 + resolution: "@adraffy/ens-normalize@npm:1.10.1" + checksum: fdd647604e8fac6204921888aaf5a6bc65eabf0d2921bc5f93b64d01f4bc33ead167c1445f7de05468d05cd92ac31b74c68d2be840c62b79d73693308f885c06 + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" @@ -1763,7 +1770,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.0.0, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.5.0, @ethersproject/abi@npm:^5.6.0, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": +"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.0.0, @ethersproject/abi@npm:^5.0.9, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.5.0, @ethersproject/abi@npm:^5.6.0, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abi@npm:5.7.0" dependencies: @@ -2917,6 +2924,40 @@ __metadata: languageName: unknown linkType: soft +"@graphprotocol/horizon@workspace:packages/horizon": + version: 0.0.0-use.local + resolution: "@graphprotocol/horizon@workspace:packages/horizon" + dependencies: + "@graphprotocol/contracts": "workspace:^7.0.0" + "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.0" + "@nomicfoundation/hardhat-ethers": "npm:^3.0.0" + "@nomicfoundation/hardhat-foundry": "npm:^1.1.1" + "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0" + "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" + "@nomicfoundation/hardhat-verify": "npm:^2.0.0" + "@typechain/ethers-v6": "npm:^0.5.0" + "@typechain/hardhat": "npm:^9.0.0" + "@types/chai": "npm:^4.2.0" + "@types/mocha": "npm:>=9.1.0" + "@types/node": "npm:>=16.0.0" + chai: "npm:^4.2.0" + eslint: "npm:^8.56.0" + eslint-graph-config: "workspace:^0.0.1" + ethers: "npm:^6.4.0" + hardhat: "npm:^2.20.1" + hardhat-gas-reporter: "npm:^1.0.8" + lint-staged: "npm:^15.2.2" + prettier: "npm:^3.2.5" + prettier-plugin-solidity: "npm:^1.3.1" + solhint: "npm:^4.5.2" + solhint-graph-config: "workspace:^0.0.1" + solidity-coverage: "npm:^0.8.0" + ts-node: "npm:>=8.0.0" + typechain: "npm:^8.3.0" + typescript: "npm:^5.3.3" + languageName: unknown + linkType: soft + "@graphprotocol/pino-sentry-simple@npm:0.7.1": version: 0.7.1 resolution: "@graphprotocol/pino-sentry-simple@npm:0.7.1" @@ -4034,6 +4075,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" + dependencies: + "@noble/hashes": "npm:1.3.2" + checksum: 0bac7d1bbfb3c2286910b02598addd33243cb97c3f36f987ecc927a4be8d7d88e0fcb12b0f0ef8a044e7307d1844dd5c49bb724bfa0a79c8ec50ba60768c97f6 + languageName: node + linkType: hard + "@noble/curves@npm:1.3.0, @noble/curves@npm:~1.3.0": version: 1.3.0 resolution: "@noble/curves@npm:1.3.0" @@ -4050,6 +4100,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.3.2": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: 2482cce3bce6a596626f94ca296e21378e7a5d4c09597cbc46e65ffacc3d64c8df73111f2265444e36a3168208628258bbbaccba2ef24f65f58b2417638a20e7 + languageName: node + linkType: hard + "@noble/hashes@npm:1.3.3, @noble/hashes@npm:~1.3.2": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" @@ -4091,6 +4148,105 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/edr-darwin-arm64@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.2.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@nomicfoundation/edr-darwin-x64@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-darwin-x64@npm:0.2.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-arm64-gnu@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.2.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-arm64-musl@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.2.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-x64-gnu@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.2.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-x64-musl@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.2.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@nomicfoundation/edr-win32-arm64-msvc@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-win32-arm64-msvc@npm:0.2.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@nomicfoundation/edr-win32-ia32-msvc@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-win32-ia32-msvc@npm:0.2.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@nomicfoundation/edr-win32-x64-msvc@npm:0.2.1": + version: 0.2.1 + resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.2.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@nomicfoundation/edr@npm:^0.2.0": + version: 0.2.1 + resolution: "@nomicfoundation/edr@npm:0.2.1" + dependencies: + "@nomicfoundation/edr-darwin-arm64": "npm:0.2.1" + "@nomicfoundation/edr-darwin-x64": "npm:0.2.1" + "@nomicfoundation/edr-linux-arm64-gnu": "npm:0.2.1" + "@nomicfoundation/edr-linux-arm64-musl": "npm:0.2.1" + "@nomicfoundation/edr-linux-x64-gnu": "npm:0.2.1" + "@nomicfoundation/edr-linux-x64-musl": "npm:0.2.1" + "@nomicfoundation/edr-win32-arm64-msvc": "npm:0.2.1" + "@nomicfoundation/edr-win32-ia32-msvc": "npm:0.2.1" + "@nomicfoundation/edr-win32-x64-msvc": "npm:0.2.1" + dependenciesMeta: + "@nomicfoundation/edr-darwin-arm64": + optional: true + "@nomicfoundation/edr-darwin-x64": + optional: true + "@nomicfoundation/edr-linux-arm64-gnu": + optional: true + "@nomicfoundation/edr-linux-arm64-musl": + optional: true + "@nomicfoundation/edr-linux-x64-gnu": + optional: true + "@nomicfoundation/edr-linux-x64-musl": + optional: true + "@nomicfoundation/edr-win32-arm64-msvc": + optional: true + "@nomicfoundation/edr-win32-ia32-msvc": + optional: true + "@nomicfoundation/edr-win32-x64-msvc": + optional: true + checksum: e8956284c14fb47662c92368ed17d871a24876a27c2e6525c99fabfe41cadb7d6f403889802216691ba41c38ee055c9cd59befc48f7b8018002ac2d09d2da29b + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-block@npm:4.2.2": version: 4.2.2 resolution: "@nomicfoundation/ethereumjs-block@npm:4.2.2" @@ -4582,7 +4738,48 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/hardhat-network-helpers@npm:^1.0.9": +"@nomicfoundation/hardhat-chai-matchers@npm:^2.0.0": + version: 2.0.6 + resolution: "@nomicfoundation/hardhat-chai-matchers@npm:2.0.6" + dependencies: + "@types/chai-as-promised": "npm:^7.1.3" + chai-as-promised: "npm:^7.1.1" + deep-eql: "npm:^4.0.1" + ordinal: "npm:^1.0.3" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.0 + chai: ^4.2.0 + ethers: ^6.1.0 + hardhat: ^2.9.4 + checksum: 0d65a0b0a552391ee3b20db9ffc9559138c02bc9c9cdd30106c9b5247d5a9e9b412480772faecab210a8cade0dfcddce3b04f5d3f3371e80085d6883a917dfe5 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-ethers@npm:^3.0.0": + version: 3.0.5 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.5" + dependencies: + debug: "npm:^4.1.1" + lodash.isequal: "npm:^4.5.0" + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + checksum: 8253d107f956fbbfcb55b758cfd05159dcc77289bc115418626c3be32efeaced82c7dbfcb9d67ef0d9dccb6851e8588edeb228f325982ac3c61d7f605bcef009 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-foundry@npm:^1.1.1": + version: 1.1.1 + resolution: "@nomicfoundation/hardhat-foundry@npm:1.1.1" + dependencies: + chalk: "npm:^2.4.2" + peerDependencies: + hardhat: ^2.17.2 + checksum: e1f914bd705b93c9efc9f0b30eb178288504aede202ec00a9b03d3fa494baf175d0218ee678a328179b1ecfe18e16184888f671e8a03488e4ebfba0daf93a603 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-network-helpers@npm:^1.0.0, @nomicfoundation/hardhat-network-helpers@npm:^1.0.9": version: 1.0.10 resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.0.10" dependencies: @@ -4593,6 +4790,50 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/hardhat-toolbox@npm:^4.0.0": + version: 4.0.0 + resolution: "@nomicfoundation/hardhat-toolbox@npm:4.0.0" + peerDependencies: + "@nomicfoundation/hardhat-chai-matchers": ^2.0.0 + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-network-helpers": ^1.0.0 + "@nomicfoundation/hardhat-verify": ^2.0.0 + "@typechain/ethers-v6": ^0.5.0 + "@typechain/hardhat": ^9.0.0 + "@types/chai": ^4.2.0 + "@types/mocha": ">=9.1.0" + "@types/node": ">=16.0.0" + chai: ^4.2.0 + ethers: ^6.4.0 + hardhat: ^2.11.0 + hardhat-gas-reporter: ^1.0.8 + solidity-coverage: ^0.8.1 + ts-node: ">=8.0.0" + typechain: ^8.3.0 + typescript: ">=4.5.0" + checksum: 9de2511cee509754afd4631f5f1497160bf4d3ecea741e9deeb22a6e662e16ce7ba37cffe836d30a958f08719c0c5906decc3c73df6a5d90c248b4654c8b15d1 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-verify@npm:^2.0.0": + version: 2.0.4 + resolution: "@nomicfoundation/hardhat-verify@npm:2.0.4" + dependencies: + "@ethersproject/abi": "npm:^5.1.2" + "@ethersproject/address": "npm:^5.0.2" + cbor: "npm:^8.1.0" + chalk: "npm:^2.4.2" + debug: "npm:^4.1.1" + lodash.clonedeep: "npm:^4.5.0" + semver: "npm:^6.3.0" + table: "npm:^6.8.0" + undici: "npm:^5.14.0" + peerDependencies: + hardhat: ^2.0.4 + checksum: 9003db2eb06aad8764473240d5ddb0cdef27b9bd7ed4586469aec8997d4556a1b1f11c537b567e3a30af694ac5d756dc9cccc52c14604e92d0dfdc964d12c6e8 + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1" @@ -5505,6 +5746,20 @@ __metadata: languageName: node linkType: hard +"@typechain/ethers-v6@npm:^0.5.0": + version: 0.5.1 + resolution: "@typechain/ethers-v6@npm:0.5.1" + dependencies: + lodash: "npm:^4.17.15" + ts-essentials: "npm:^7.0.1" + peerDependencies: + ethers: 6.x + typechain: ^8.3.2 + typescript: ">=4.7.0" + checksum: f3c80151c07e01adbf520e0854426649edb0ee540920569487dd8da7eca2fa8615710f4c0eda008e7afdf255fbb8dfdebf721a5d324a4dffeb087611d9bd64b9 + languageName: node + linkType: hard + "@typechain/hardhat@npm:^2.0.0": version: 2.3.1 resolution: "@typechain/hardhat@npm:2.3.1" @@ -5531,6 +5786,20 @@ __metadata: languageName: node linkType: hard +"@typechain/hardhat@npm:^9.0.0": + version: 9.1.0 + resolution: "@typechain/hardhat@npm:9.1.0" + dependencies: + fs-extra: "npm:^9.1.0" + peerDependencies: + "@typechain/ethers-v6": ^0.5.1 + ethers: ^6.1.0 + hardhat: ^2.9.9 + typechain: ^8.3.2 + checksum: 3a1220efefc7b02ca335696167f6c5332a33ff3fbf9f20552468566a1760f76bc88d330683e97ca6213eb9518a2a901391c31c84c0548006b72bd2ec62d4af9c + languageName: node + linkType: hard + "@types/async-eventemitter@npm:^0.2.1": version: 0.2.4 resolution: "@types/async-eventemitter@npm:0.2.4" @@ -5580,7 +5849,7 @@ __metadata: languageName: node linkType: hard -"@types/chai-as-promised@npm:^7.1.5, @types/chai-as-promised@npm:^7.1.7": +"@types/chai-as-promised@npm:^7.1.3, @types/chai-as-promised@npm:^7.1.5, @types/chai-as-promised@npm:^7.1.7": version: 7.1.8 resolution: "@types/chai-as-promised@npm:7.1.8" dependencies: @@ -5589,7 +5858,7 @@ __metadata: languageName: node linkType: hard -"@types/chai@npm:*, @types/chai@npm:^4.3.9": +"@types/chai@npm:*, @types/chai@npm:^4.2.0, @types/chai@npm:^4.3.9": version: 4.3.12 resolution: "@types/chai@npm:4.3.12" checksum: e5d952726d7f053812579962b07d0e4965c160c6a90bf466580e639cd3a1f1d30da1abbfe782383538a043a07908f9dfb823fa9065b37752a5f27d62234f44d5 @@ -5755,7 +6024,7 @@ __metadata: languageName: node linkType: hard -"@types/mocha@npm:^10.0.3": +"@types/mocha@npm:>=9.1.0, @types/mocha@npm:^10.0.3": version: 10.0.6 resolution: "@types/mocha@npm:10.0.6" checksum: 4526c9e88388f9e1004c6d3937c5488a39908810f26b927173c58d52b43057f3895627dc06538e96706e08b88158885f869ec6311f6b58fd72bdef715f26d6c3 @@ -5802,6 +6071,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: 6e5f61c559e60670a7a8fb88e31226ecc18a21be103297ca4cf9848f0a99049dae77f04b7ae677205f2af494f3701b113ba8734f4b636b355477a6534dbb8ada + languageName: node + linkType: hard + "@types/node@npm:>=12": version: 20.11.30 resolution: "@types/node@npm:20.11.30" @@ -5811,6 +6087,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:>=16.0.0": + version: 20.11.26 + resolution: "@types/node@npm:20.11.26" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 2df81e4f109588c4c490f2c7d616a06d2b3b9298f217468134b80711af810c9a6017a59beb3e6b1c596eb9b6c5a39d33403b99179acb89006badfbc55f2468bb + languageName: node + linkType: hard + "@types/node@npm:^10.0.3": version: 10.17.60 resolution: "@types/node@npm:10.17.60" @@ -6556,6 +6841,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: 444f4eefa1e602cbc4f2a3c644bc990f93fd982b148425fee17634da510586fc09da940dcf8ace1b2d001453c07ff042e55f7a0482b3cc9372bf1ef75479090c + languageName: node + linkType: hard + "aes-js@npm:^3.1.1": version: 3.1.2 resolution: "aes-js@npm:3.1.2" @@ -6693,6 +6985,15 @@ __metadata: languageName: node linkType: hard +"ansi-escapes@npm:^6.2.0": + version: 6.2.0 + resolution: "ansi-escapes@npm:6.2.0" + dependencies: + type-fest: "npm:^3.0.0" + checksum: 3eec75deedd8b10192c5f98e4cd9715cc3ff268d33fc463c24b7d22446668bfcd4ad1803993ea89c0f51f88b5a3399572bacb7c8cb1a067fc86e189c5f3b0c7e + languageName: node + linkType: hard + "ansi-regex@npm:^2.0.0": version: 2.1.1 resolution: "ansi-regex@npm:2.1.1" @@ -6753,7 +7054,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0": +"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": version: 6.2.1 resolution: "ansi-styles@npm:6.2.1" checksum: 5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c @@ -8855,6 +9156,13 @@ __metadata: languageName: node linkType: hard +"chalk@npm:5.3.0": + version: 5.3.0 + resolution: "chalk@npm:5.3.0" + checksum: 8297d436b2c0f95801103ff2ef67268d362021b8210daf8ddbe349695333eb3610a71122172ff3b0272f1ef2cf7cc2c41fdaa4715f52e49ffe04c56340feed09 + languageName: node + linkType: hard + "chalk@npm:^1.1.3": version: 1.1.3 resolution: "chalk@npm:1.1.3" @@ -9154,6 +9462,15 @@ __metadata: languageName: node linkType: hard +"cli-cursor@npm:^4.0.0": + version: 4.0.0 + resolution: "cli-cursor@npm:4.0.0" + dependencies: + restore-cursor: "npm:^4.0.0" + checksum: e776e8c3c6727300d0539b0d25160b2bb56aed1a63942753ba1826b012f337a6f4b7ace3548402e4f2f13b5e16bfd751be672c44b203205e7eca8be94afec42c + languageName: node + linkType: hard + "cli-spinners@npm:^2.5.0": version: 2.9.2 resolution: "cli-spinners@npm:2.9.2" @@ -9217,6 +9534,16 @@ __metadata: languageName: node linkType: hard +"cli-truncate@npm:^4.0.0": + version: 4.0.0 + resolution: "cli-truncate@npm:4.0.0" + dependencies: + slice-ansi: "npm:^5.0.0" + string-width: "npm:^7.0.0" + checksum: d7f0b73e3d9b88cb496e6c086df7410b541b56a43d18ade6a573c9c18bd001b1c3fba1ad578f741a4218fdc794d042385f8ac02c25e1c295a2d8b9f3cb86eb4c + languageName: node + linkType: hard + "cli-width@npm:^3.0.0": version: 3.0.0 resolution: "cli-width@npm:3.0.0" @@ -9385,7 +9712,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.16": +"colorette@npm:^2.0.16, colorette@npm:^2.0.20": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: e94116ff33b0ff56f3b83b9ace895e5bf87c2a7a47b3401b8c3f3226e050d5ef76cf4072fb3325f9dc24d1698f9b730baf4e05eeaf861d74a1883073f4c98a40 @@ -9469,6 +9796,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:11.1.0, commander@npm:^11.1.0": + version: 11.1.0 + resolution: "commander@npm:11.1.0" + checksum: 13cc6ac875e48780250f723fb81c1c1178d35c5decb1abb1b628b3177af08a8554e76b2c0f29de72d69eef7c864d12613272a71fabef8047922bc622ab75a179 + languageName: node + linkType: hard + "commander@npm:2.11.0": version: 2.11.0 resolution: "commander@npm:2.11.0" @@ -9490,13 +9824,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^11.1.0": - version: 11.1.0 - resolution: "commander@npm:11.1.0" - checksum: 13cc6ac875e48780250f723fb81c1c1178d35c5decb1abb1b628b3177af08a8554e76b2c0f29de72d69eef7c864d12613272a71fabef8047922bc622ab75a179 - languageName: node - linkType: hard - "commander@npm:^2.15.0, commander@npm:^2.9.0": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -10180,7 +10507,7 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.1.3": +"deep-eql@npm:^4.0.1, deep-eql@npm:^4.1.3": version: 4.1.3 resolution: "deep-eql@npm:4.1.3" dependencies: @@ -10471,6 +10798,15 @@ __metadata: languageName: node linkType: hard +"difflib@npm:^0.2.4": + version: 0.2.4 + resolution: "difflib@npm:0.2.4" + dependencies: + heap: "npm:>= 0.2.0" + checksum: 4b151f1f6d378b0837ef28f4706d89d05b78f1093253b06c975c621f7ef8b048978588baf9e8f284c64b133d0abb08303b0789519cc91e5180d420cb3bb99c05 + languageName: node + linkType: hard + "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -10640,6 +10976,13 @@ __metadata: languageName: node linkType: hard +"emoji-regex@npm:^10.3.0": + version: 10.3.0 + resolution: "emoji-regex@npm:10.3.0" + checksum: b4838e8dcdceb44cf47f59abe352c25ff4fe7857acaf5fb51097c427f6f75b44d052eb907a7a3b86f86bc4eae3a93f5c2b7460abe79c407307e6212d65c91163 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -11854,6 +12197,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.4.0": + version: 6.11.1 + resolution: "ethers@npm:6.11.1" + dependencies: + "@adraffy/ens-normalize": "npm:1.10.1" + "@noble/curves": "npm:1.2.0" + "@noble/hashes": "npm:1.3.2" + "@types/node": "npm:18.15.13" + aes-js: "npm:4.0.0-beta.5" + tslib: "npm:2.4.0" + ws: "npm:8.5.0" + checksum: 97a920e0244ba6cd1622b58a448c87f26dad20bad242777abb2e583d045bf7752218477bd7367ba6518c2a5e2b16030afff15e87b705526d0ea667498c27ac89 + languageName: node + linkType: hard + "ethjs-unit@npm:0.1.6": version: 0.1.6 resolution: "ethjs-unit@npm:0.1.6" @@ -11928,6 +12286,13 @@ __metadata: languageName: node linkType: hard +"eventemitter3@npm:^5.0.1": + version: 5.0.1 + resolution: "eventemitter3@npm:5.0.1" + checksum: 4ba5c00c506e6c786b4d6262cfbce90ddc14c10d4667e5c83ae993c9de88aa856033994dd2b35b83e8dc1170e224e66a319fa80adc4c32adcd2379bbc75da814 + languageName: node + linkType: hard + "events@npm:^3.0.0": version: 3.3.0 resolution: "events@npm:3.3.0" @@ -11946,6 +12311,23 @@ __metadata: languageName: node linkType: hard +"execa@npm:8.0.1": + version: 8.0.1 + resolution: "execa@npm:8.0.1" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^8.0.1" + human-signals: "npm:^5.0.0" + is-stream: "npm:^3.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^5.1.0" + onetime: "npm:^6.0.0" + signal-exit: "npm:^4.1.0" + strip-final-newline: "npm:^3.0.0" + checksum: 2c52d8775f5bf103ce8eec9c7ab3059909ba350a5164744e9947ed14a53f51687c040a250bda833f906d1283aa8803975b84e6c8f7a7c42f99dc8ef80250d1af + languageName: node + linkType: hard + "execa@npm:^0.7.0": version: 0.7.0 resolution: "execa@npm:0.7.0" @@ -13080,6 +13462,13 @@ __metadata: languageName: node linkType: hard +"get-east-asian-width@npm:^1.0.0": + version: 1.2.0 + resolution: "get-east-asian-width@npm:1.2.0" + checksum: 914b1e217cf38436c24b4c60b4c45289e39a45bf9e65ef9fd343c2815a1a02b8a0215aeec8bf9c07c516089004b6e3826332481f40a09529fcadbf6e579f286b + languageName: node + linkType: hard + "get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": version: 2.0.2 resolution: "get-func-name@npm:2.0.2" @@ -13153,6 +13542,13 @@ __metadata: languageName: node linkType: hard +"get-stream@npm:^8.0.1": + version: 8.0.1 + resolution: "get-stream@npm:8.0.1" + checksum: 5c2181e98202b9dae0bb4a849979291043e5892eb40312b47f0c22b9414fc9b28a3b6063d2375705eb24abc41ecf97894d9a51f64ff021511b504477b27b4290 + languageName: node + linkType: hard + "get-symbol-description@npm:^1.0.2": version: 1.0.2 resolution: "get-symbol-description@npm:1.0.2" @@ -13258,6 +13654,20 @@ __metadata: languageName: node linkType: hard +"glob@npm:7.1.7": + version: 7.1.7 + resolution: "glob@npm:7.1.7" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^3.0.4" + once: "npm:^1.3.0" + path-is-absolute: "npm:^1.0.0" + checksum: 173245e6f9ccf904309eb7ef4a44a11f3bf68e9e341dff5a28b5db0dd7123b7506daf41497f3437a0710f57198187b758c2351eeaabce4d16935e956920da6a4 + languageName: node + linkType: hard + "glob@npm:7.2.0": version: 7.2.0 resolution: "glob@npm:7.2.0" @@ -13761,7 +14171,7 @@ __metadata: languageName: node linkType: hard -"hardhat-gas-reporter@npm:^1.0.1, hardhat-gas-reporter@npm:^1.0.4": +"hardhat-gas-reporter@npm:^1.0.1, hardhat-gas-reporter@npm:^1.0.4, hardhat-gas-reporter@npm:^1.0.8": version: 1.0.10 resolution: "hardhat-gas-reporter@npm:1.0.10" dependencies: @@ -13830,6 +14240,67 @@ __metadata: languageName: node linkType: hard +"hardhat@npm:^2.20.1": + version: 2.21.0 + resolution: "hardhat@npm:2.21.0" + dependencies: + "@ethersproject/abi": "npm:^5.1.2" + "@metamask/eth-sig-util": "npm:^4.0.0" + "@nomicfoundation/edr": "npm:^0.2.0" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" + "@nomicfoundation/solidity-analyzer": "npm:^0.1.0" + "@sentry/node": "npm:^5.18.1" + "@types/bn.js": "npm:^5.1.0" + "@types/lru-cache": "npm:^5.1.0" + adm-zip: "npm:^0.4.16" + aggregate-error: "npm:^3.0.0" + ansi-escapes: "npm:^4.3.0" + boxen: "npm:^5.1.2" + chalk: "npm:^2.4.2" + chokidar: "npm:^3.4.0" + ci-info: "npm:^2.0.0" + debug: "npm:^4.1.1" + enquirer: "npm:^2.3.0" + env-paths: "npm:^2.2.0" + ethereum-cryptography: "npm:^1.0.3" + ethereumjs-abi: "npm:^0.6.8" + find-up: "npm:^2.1.0" + fp-ts: "npm:1.19.3" + fs-extra: "npm:^7.0.1" + glob: "npm:7.2.0" + immutable: "npm:^4.0.0-rc.12" + io-ts: "npm:1.10.4" + keccak: "npm:^3.0.2" + lodash: "npm:^4.17.11" + mnemonist: "npm:^0.38.0" + mocha: "npm:^10.0.0" + p-map: "npm:^4.0.0" + raw-body: "npm:^2.4.1" + resolve: "npm:1.17.0" + semver: "npm:^6.3.0" + solc: "npm:0.7.3" + source-map-support: "npm:^0.5.13" + stacktrace-parser: "npm:^0.1.10" + tsort: "npm:0.0.1" + undici: "npm:^5.14.0" + uuid: "npm:^8.3.2" + ws: "npm:^7.4.6" + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + bin: + hardhat: internal/cli/bootstrap.js + checksum: d7c887d147ddbd0792b5e64abfd8200c233a1815b91af908f68b167067e109f9ab6e0892d130137a745c6139bae691cee62a8e993290d4fc0a2a733e5dcce324 + languageName: node + linkType: hard + "hardhat@npm:^2.6.1, hardhat@npm:^2.6.4": version: 2.20.1 resolution: "hardhat@npm:2.20.1" @@ -14170,6 +14641,13 @@ __metadata: languageName: node linkType: hard +"heap@npm:>= 0.2.0": + version: 0.2.7 + resolution: "heap@npm:0.2.7" + checksum: 341c5d51ae13dc8346c371a8a69c57c972fcb9a3233090d3dd5ba29d483d6b5b4e75492443cbfeacd46608bb30e6680f646ffb7a6205900221735587d07a79b6 + languageName: node + linkType: hard + "helmet@npm:5.0.2": version: 5.0.2 resolution: "helmet@npm:5.0.2" @@ -14371,6 +14849,13 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^5.0.0": + version: 5.0.0 + resolution: "human-signals@npm:5.0.0" + checksum: 5a9359073fe17a8b58e5a085e9a39a950366d9f00217c4ff5878bd312e09d80f460536ea6a3f260b5943a01fe55c158d1cea3fc7bee3d0520aeef04f6d915c82 + languageName: node + linkType: hard + "husky@npm:^7.0.4": version: 7.0.4 resolution: "husky@npm:7.0.4" @@ -15060,6 +15545,15 @@ __metadata: languageName: node linkType: hard +"is-fullwidth-code-point@npm:^5.0.0": + version: 5.0.0 + resolution: "is-fullwidth-code-point@npm:5.0.0" + dependencies: + get-east-asian-width: "npm:^1.0.0" + checksum: cd591b27d43d76b05fa65ed03eddce57a16e1eca0b7797ff7255de97019bcaf0219acfc0c4f7af13319e13541f2a53c0ace476f442b13267b9a6a7568f2b65c8 + languageName: node + linkType: hard + "is-function@npm:^1.0.1": version: 1.0.2 resolution: "is-function@npm:1.0.2" @@ -15288,6 +15782,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: eb2f7127af02ee9aa2a0237b730e47ac2de0d4e76a4a905a50a11557f2339df5765eaea4ceb8029f1efa978586abe776908720bfcb1900c20c6ec5145f6f29d8 + languageName: node + linkType: hard + "is-string@npm:^1.0.5, is-string@npm:^1.0.7": version: 1.0.7 resolution: "is-string@npm:1.0.7" @@ -16333,6 +16834,13 @@ __metadata: languageName: node linkType: hard +"lilconfig@npm:3.0.0": + version: 3.0.0 + resolution: "lilconfig@npm:3.0.0" + checksum: 7f5ee7a658dc016cacf146815e8d88b06f06f4402823b8b0934e305a57a197f55ccc9c5cd4fb5ea1b2b821c8ccaf2d54abd59602a4931af06eabda332388d3e6 + languageName: node + linkType: hard + "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -16389,6 +16897,40 @@ __metadata: languageName: node linkType: hard +"lint-staged@npm:^15.2.2": + version: 15.2.2 + resolution: "lint-staged@npm:15.2.2" + dependencies: + chalk: "npm:5.3.0" + commander: "npm:11.1.0" + debug: "npm:4.3.4" + execa: "npm:8.0.1" + lilconfig: "npm:3.0.0" + listr2: "npm:8.0.1" + micromatch: "npm:4.0.5" + pidtree: "npm:0.6.0" + string-argv: "npm:0.3.2" + yaml: "npm:2.3.4" + bin: + lint-staged: bin/lint-staged.js + checksum: a1ba6c7ee53e30a0f6ea9a351d95d3d0d2be916a41b561e22907e9ea513eb18cb3dbe65bff3ec13fad15777999efe56b2e2a95427e31d12a9b7e7948c3630ee2 + languageName: node + linkType: hard + +"listr2@npm:8.0.1": + version: 8.0.1 + resolution: "listr2@npm:8.0.1" + dependencies: + cli-truncate: "npm:^4.0.0" + colorette: "npm:^2.0.20" + eventemitter3: "npm:^5.0.1" + log-update: "npm:^6.0.0" + rfdc: "npm:^1.3.0" + wrap-ansi: "npm:^9.0.0" + checksum: b565d6ceb3a4c2dbe0c1735c0fd907afd0d6f89de21aced8e05187b2d88ca2f8f9ebc5d743885396a00f05f13146f6be744d098a56ce0402cf1cd131485a7ff1 + languageName: node + linkType: hard + "listr2@npm:^3.2.2": version: 3.14.0 resolution: "listr2@npm:3.14.0" @@ -16655,6 +17197,19 @@ __metadata: languageName: node linkType: hard +"log-update@npm:^6.0.0": + version: 6.0.0 + resolution: "log-update@npm:6.0.0" + dependencies: + ansi-escapes: "npm:^6.2.0" + cli-cursor: "npm:^4.0.0" + slice-ansi: "npm:^7.0.0" + strip-ansi: "npm:^7.1.0" + wrap-ansi: "npm:^9.0.0" + checksum: e0b3c3401ef49ce3eb17e2f83d644765e4f7988498fc1344eaa4f31ab30e510dcc469a7fb64dc01bd1c8d9237d917598fa677a9818705fb3774c10f6e9d4b27c + languageName: node + linkType: hard + "logform@npm:^2.3.2, logform@npm:^2.4.0": version: 2.6.0 resolution: "logform@npm:2.6.0" @@ -17103,6 +17658,16 @@ __metadata: languageName: node linkType: hard +"micromatch@npm:4.0.5, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": + version: 4.0.5 + resolution: "micromatch@npm:4.0.5" + dependencies: + braces: "npm:^3.0.2" + picomatch: "npm:^2.3.1" + checksum: 3d6505b20f9fa804af5d8c596cb1c5e475b9b0cd05f652c5b56141cf941bd72adaeb7a436fda344235cef93a7f29b7472efc779fcdb83b478eab0867b95cdeff + languageName: node + linkType: hard + "micromatch@npm:^2.1.5": version: 2.3.11 resolution: "micromatch@npm:2.3.11" @@ -17145,16 +17710,6 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" - dependencies: - braces: "npm:^3.0.2" - picomatch: "npm:^2.3.1" - checksum: 3d6505b20f9fa804af5d8c596cb1c5e475b9b0cd05f652c5b56141cf941bd72adaeb7a436fda344235cef93a7f29b7472efc779fcdb83b478eab0867b95cdeff - languageName: node - linkType: hard - "miller-rabin@npm:^4.0.0": version: 4.0.1 resolution: "miller-rabin@npm:4.0.1" @@ -17206,6 +17761,13 @@ __metadata: languageName: node linkType: hard +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: de9cc32be9996fd941e512248338e43407f63f6d497abe8441fa33447d922e927de54d4cc3c1a3c6d652857acd770389d5a3823f311a744132760ce2be15ccbf + languageName: node + linkType: hard + "mimic-response@npm:^1.0.0, mimic-response@npm:^1.0.1": version: 1.0.1 resolution: "mimic-response@npm:1.0.1" @@ -18129,6 +18691,15 @@ __metadata: languageName: node linkType: hard +"npm-run-path@npm:^5.1.0": + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" + dependencies: + path-key: "npm:^4.0.0" + checksum: 124df74820c40c2eb9a8612a254ea1d557ddfab1581c3e751f825e3e366d9f00b0d76a3c94ecd8398e7f3eee193018622677e95816e8491f0797b21e30b2deba + languageName: node + linkType: hard + "nullthrows@npm:^1.1.1": version: 1.1.1 resolution: "nullthrows@npm:1.1.1" @@ -18360,6 +18931,15 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: "npm:^4.0.0" + checksum: 4eef7c6abfef697dd4479345a4100c382d73c149d2d56170a54a07418c50816937ad09500e1ed1e79d235989d073a9bade8557122aee24f0576ecde0f392bb6c + languageName: node + linkType: hard + "open@npm:^7.4.2": version: 7.4.2 resolution: "open@npm:7.4.2" @@ -18433,6 +19013,13 @@ __metadata: languageName: node linkType: hard +"ordinal@npm:^1.0.3": + version: 1.0.3 + resolution: "ordinal@npm:1.0.3" + checksum: faa276fc1b1660477fd5c8749323c9715ae4f482c21fb8e67e57d1eb57845ba1b902796ecdcf6405325a8c3b042360970f5dc3b7f8cc7d79e0b2a756ab09174d + languageName: node + linkType: hard + "os-homedir@npm:^1.0.0": version: 1.0.2 resolution: "os-homedir@npm:1.0.2" @@ -18878,6 +19465,13 @@ __metadata: languageName: node linkType: hard +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 794efeef32863a65ac312f3c0b0a99f921f3e827ff63afa5cb09a377e202c262b671f7b3832a4e64731003fa94af0263713962d317b9887bd1e0c48a342efba3 + languageName: node + linkType: hard + "path-parse@npm:^1.0.6, path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -19112,6 +19706,15 @@ __metadata: languageName: node linkType: hard +"pidtree@npm:0.6.0": + version: 0.6.0 + resolution: "pidtree@npm:0.6.0" + bin: + pidtree: bin/pidtree.js + checksum: 0829ec4e9209e230f74ebf4265f5ccc9ebfb488334b525cb13f86ff801dca44b362c41252cd43ae4d7653a10a5c6ab3be39d2c79064d6895e0d78dc50a5ed6e9 + languageName: node + linkType: hard + "pidtree@npm:^0.5.0": version: 0.5.0 resolution: "pidtree@npm:0.5.0" @@ -19363,7 +19966,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^2.1.1, prettier@npm:^2.1.2, prettier@npm:^2.7.1, prettier@npm:^2.8.3": +"prettier@npm:^2.1.1, prettier@npm:^2.1.2, prettier@npm:^2.3.1, prettier@npm:^2.7.1, prettier@npm:^2.8.3": version: 2.8.8 resolution: "prettier@npm:2.8.8" bin: @@ -20462,6 +21065,16 @@ __metadata: languageName: node linkType: hard +"restore-cursor@npm:^4.0.0": + version: 4.0.0 + resolution: "restore-cursor@npm:4.0.0" + dependencies: + onetime: "npm:^5.1.0" + signal-exit: "npm:^3.0.2" + checksum: 6f7da8c5e422ac26aa38354870b1afac09963572cf2879443540449068cb43476e9cbccf6f8de3e0171e0d6f7f533c2bc1a0a008003c9a525bbc098e89041318 + languageName: node + linkType: hard + "ret@npm:~0.1.10": version: 0.1.15 resolution: "ret@npm:0.1.15" @@ -21189,7 +21802,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.0.1": +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 @@ -21306,6 +21919,16 @@ __metadata: languageName: node linkType: hard +"slice-ansi@npm:^7.0.0": + version: 7.1.0 + resolution: "slice-ansi@npm:7.1.0" + dependencies: + ansi-styles: "npm:^6.2.1" + is-fullwidth-code-point: "npm:^5.0.0" + checksum: 631c971d4abf56cf880f034d43fcc44ff883624867bf11ecbd538c47343911d734a4656d7bc02362b40b89d765652a7f935595441e519b59e2ad3f4d5d6fe7ca + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -21624,6 +22247,37 @@ __metadata: languageName: node linkType: hard +"solidity-coverage@npm:^0.8.0": + version: 0.8.11 + resolution: "solidity-coverage@npm:0.8.11" + dependencies: + "@ethersproject/abi": "npm:^5.0.9" + "@solidity-parser/parser": "npm:^0.18.0" + chalk: "npm:^2.4.2" + death: "npm:^1.1.0" + difflib: "npm:^0.2.4" + fs-extra: "npm:^8.1.0" + ghost-testrpc: "npm:^0.0.2" + global-modules: "npm:^2.0.0" + globby: "npm:^10.0.1" + jsonschema: "npm:^1.2.4" + lodash: "npm:^4.17.15" + mocha: "npm:^10.2.0" + node-emoji: "npm:^1.10.0" + pify: "npm:^4.0.1" + recursive-readdir: "npm:^2.2.2" + sc-istanbul: "npm:^0.4.5" + semver: "npm:^7.3.4" + shelljs: "npm:^0.8.3" + web3-utils: "npm:^1.3.6" + peerDependencies: + hardhat: ^2.11.0 + bin: + solidity-coverage: plugins/bin.js + checksum: de26a3bdece5b36005fcf84b4c4e9e0affc2822d69c823d925f439876c3d5c7b1fc83d447745c6aae994ad0e5c02f4c031d4d9b2d5613184d9286116857e6437 + languageName: node + linkType: hard + "solium-plugin-security@npm:0.1.1": version: 0.1.1 resolution: "solium-plugin-security@npm:0.1.1" @@ -21952,7 +22606,7 @@ __metadata: languageName: node linkType: hard -"string-argv@npm:^0.3.1": +"string-argv@npm:0.3.2, string-argv@npm:^0.3.1": version: 0.3.2 resolution: "string-argv@npm:0.3.2" checksum: 75c02a83759ad1722e040b86823909d9a2fc75d15dd71ec4b537c3560746e33b5f5a07f7332d1e3f88319909f82190843aa2f0a0d8c8d591ec08e93d5b8dec82 @@ -22009,6 +22663,17 @@ __metadata: languageName: node linkType: hard +"string-width@npm:^7.0.0": + version: 7.1.0 + resolution: "string-width@npm:7.1.0" + dependencies: + emoji-regex: "npm:^10.3.0" + get-east-asian-width: "npm:^1.0.0" + strip-ansi: "npm:^7.1.0" + checksum: 68a99fbc3bd3d8eb42886ff38dce819767dee55f606f74dfa4687a07dfd21262745d9683df0aa53bf81a5dd47c13da921a501925b974bec66a7ddd634fef0634 + languageName: node + linkType: hard + "string.prototype.trim@npm:^1.2.8, string.prototype.trim@npm:~1.2.8": version: 1.2.8 resolution: "string.prototype.trim@npm:1.2.8" @@ -22114,7 +22779,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1": +"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": version: 7.1.0 resolution: "strip-ansi@npm:7.1.0" dependencies: @@ -22153,6 +22818,13 @@ __metadata: languageName: node linkType: hard +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: a771a17901427bac6293fd416db7577e2bc1c34a19d38351e9d5478c3c415f523f391003b42ed475f27e33a78233035df183525395f731d3bfb8cdcbd4da08ce + languageName: node + linkType: hard + "strip-hex-prefix@npm:1.0.0": version: 1.0.0 resolution: "strip-hex-prefix@npm:1.0.0" @@ -22791,7 +23463,7 @@ __metadata: languageName: node linkType: hard -"ts-node@npm:^10.5.0, ts-node@npm:^10.8.1, ts-node@npm:^10.9.1": +"ts-node@npm:>=8.0.0, ts-node@npm:^10.5.0, ts-node@npm:^10.8.1, ts-node@npm:^10.9.1": version: 10.9.2 resolution: "ts-node@npm:10.9.2" dependencies: @@ -22840,6 +23512,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:2.4.0": + version: 2.4.0 + resolution: "tslib@npm:2.4.0" + checksum: eb19bda3ae545b03caea6a244b34593468e23d53b26bf8649fbc20fce43e9b21a71127fd6d2b9662c0fe48ee6ff668ead48fd00d3b88b2b716b1c12edae25b5d + languageName: node + linkType: hard + "tslib@npm:^1.11.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" @@ -23003,6 +23682,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^3.0.0": + version: 3.13.1 + resolution: "type-fest@npm:3.13.1" + checksum: 547d22186f73a8c04590b70dcf63baff390078c75ea8acd366bbd510fd0646e348bd1970e47ecf795b7cff0b41d26e9c475c1fedd6ef5c45c82075fbf916b629 + languageName: node + linkType: hard + "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -23088,6 +23774,28 @@ __metadata: languageName: node linkType: hard +"typechain@npm:^8.3.0": + version: 8.3.2 + resolution: "typechain@npm:8.3.2" + dependencies: + "@types/prettier": "npm:^2.1.1" + debug: "npm:^4.3.1" + fs-extra: "npm:^7.0.0" + glob: "npm:7.1.7" + js-sha3: "npm:^0.8.0" + lodash: "npm:^4.17.15" + mkdirp: "npm:^1.0.4" + prettier: "npm:^2.3.1" + ts-command-line-args: "npm:^2.2.0" + ts-essentials: "npm:^7.0.1" + peerDependencies: + typescript: ">=4.3.0" + bin: + typechain: dist/cli/cli.js + checksum: 1ea660cc7c699c6ac68da67b76454eb4e9395c54666d924ca67f983ae8eb5b5e7dab0a576beb55dbfad75ea784a3f68cb1ca019d332293b7291731c156ead5b5 + languageName: node + linkType: hard + "typed-array-buffer@npm:^1.0.1": version: 1.0.2 resolution: "typed-array-buffer@npm:1.0.2" @@ -24546,7 +25254,7 @@ __metadata: languageName: node linkType: hard -"web3-utils@npm:^1.0.0-beta.31, web3-utils@npm:^1.3.0": +"web3-utils@npm:^1.0.0-beta.31, web3-utils@npm:^1.3.0, web3-utils@npm:^1.3.6": version: 1.10.4 resolution: "web3-utils@npm:1.10.4" dependencies: @@ -24907,6 +25615,17 @@ __metadata: languageName: node linkType: hard +"wrap-ansi@npm:^9.0.0": + version: 9.0.0 + resolution: "wrap-ansi@npm:9.0.0" + dependencies: + ansi-styles: "npm:^6.2.1" + string-width: "npm:^7.0.0" + strip-ansi: "npm:^7.1.0" + checksum: a139b818da9573677548dd463bd626a5a5286271211eb6e4e82f34a4f643191d74e6d4a9bb0a3c26ec90e6f904f679e0569674ac099ea12378a8b98e20706066 + languageName: node + linkType: hard + "wrappy@npm:1": version: 1.0.2 resolution: "wrappy@npm:1.0.2" @@ -24944,6 +25663,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.5.0": + version: 8.5.0 + resolution: "ws@npm:8.5.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 0baeee03e97865accda8fad51e8e5fa17d19b8e264529efdf662bbba2acc1c7f1de8316287e6df5cb639231a96009e6d5234b57e6ff36ee2d04e49a0995fec2f + languageName: node + linkType: hard + "ws@npm:^3.0.0": version: 3.3.3 resolution: "ws@npm:3.3.3" @@ -25111,6 +25845,13 @@ __metadata: languageName: node linkType: hard +"yaml@npm:2.3.4": + version: 2.3.4 + resolution: "yaml@npm:2.3.4" + checksum: cf03b68f8fef5e8516b0f0b54edaf2459f1648317fc6210391cf606d247e678b449382f4bd01f77392538429e306c7cba8ff46ff6b37cac4de9a76aff33bd9e1 + languageName: node + linkType: hard + "yaml@npm:^1.10.0, yaml@npm:^1.10.2": version: 1.10.2 resolution: "yaml@npm:1.10.2" From 2cea50f11d5fd780a289fcfde4a7cfb031e8fb8f Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 10 Apr 2024 17:36:41 -0300 Subject: [PATCH 006/277] chore: add GraphEscrow --- packages/horizon/contracts/GraphEscrow.sol | 50 +++++++++++++++++++ .../horizon/contracts/GraphEscrowStorage.sol | 17 +++++++ .../contracts/interfaces/IGraphEscrow.sol | 25 ++++++++++ .../contracts/interfaces/IGraphPayments.sol | 13 +++++ packages/subgraph-service/lib/forge-std | 1 + 5 files changed, 106 insertions(+) create mode 100644 packages/horizon/contracts/GraphEscrow.sol create mode 100644 packages/horizon/contracts/GraphEscrowStorage.sol create mode 100644 packages/horizon/contracts/interfaces/IGraphEscrow.sol create mode 100644 packages/horizon/contracts/interfaces/IGraphPayments.sol create mode 160000 packages/subgraph-service/lib/forge-std diff --git a/packages/horizon/contracts/GraphEscrow.sol b/packages/horizon/contracts/GraphEscrow.sol new file mode 100644 index 000000000..a6a58c7e1 --- /dev/null +++ b/packages/horizon/contracts/GraphEscrow.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; + +import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; +import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; + +contract GraphEscrow is GraphEscrowStorageV1Storage { + // -- Errors -- + + error GraphEscrowNotGraphPayments(); + + // -- Immutable variables -- + + IGraphToken public immutable graphToken; + IGraphPayments public immutable graphPayments; + + // -- Modifier -- + + modifier onlyGraphPayments() { + if (msg.sender != address(graphPayments)) { + revert GraphEscrowNotGraphPayments(); + } + _; + } + + // -- Constructor -- + + constructor(address _graphToken, address _graphPayments, uint256 _withdrawEscrowThawingPeriod) { + graphToken = IGraphToken(_graphToken); + graphPayments = IGraphPayments(_graphPayments); + _withdrawEscrowThawingPeriod = _withdrawEscrowThawingPeriod; + } + + // Deposit funds into the escrow for a receiver + function deposit(address receiver, uint256 amount) external {} + + // Deposit funds into the escrow for multiple receivers + function depositMany(address[] calldata receivers, uint256[] calldata amounts) external {} + + // Requests to thaw a specific amount of escrow from a receiver's escrow account + function thaw(address receiver, uint256 amount) external {} + + // Withdraws all thawed escrow from a receiver's escrow account + function withdraw(address receiver) external {} + + // Collect from escrow (up to amount available in escrow) for a receiver using sender's deposit + function collect(address sender, address receiver, uint256 amount) external onlyGraphPayments {} +} diff --git a/packages/horizon/contracts/GraphEscrowStorage.sol b/packages/horizon/contracts/GraphEscrowStorage.sol new file mode 100644 index 000000000..aa8567d8b --- /dev/null +++ b/packages/horizon/contracts/GraphEscrowStorage.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; + +contract GraphEscrowStorageV1Storage { + // Stores how much escrow each sender has deposited for each receiver, as well as thawing information + mapping(address sender => mapping(address receiver => IGraphEscrow.EscrowAccount escrowAccount)) + public escrowAccounts; + + // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn + uint256 public immutable withdrawEscrowThawingPeriod; + + // The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation + // This is a precautionary measure to avoid inadvertedly locking funds for too long + uint256 public constant MAX_THAWING_PERIOD = 90 days; +} diff --git a/packages/horizon/contracts/interfaces/IGraphEscrow.sol b/packages/horizon/contracts/interfaces/IGraphEscrow.sol new file mode 100644 index 000000000..8e6ca58fd --- /dev/null +++ b/packages/horizon/contracts/interfaces/IGraphEscrow.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +interface IGraphEscrow { + struct EscrowAccount { + uint256 balance; // Total escrow balance for a sender-receiver pair + uint256 amountThawing; // Amount of escrow currently being thawed + uint256 thawEndTimestamp; // Timestamp at which thawing period ends (zero if not thawing) + } + + // Deposit funds into the escrow for a receiver + function deposit(address receiver, uint256 amount) external; + + // Deposit funds into the escrow for multiple receivers + function depositMany(address[] calldata receivers, uint256[] calldata amounts) external; + + // Requests to thaw a specific amount of escrow from a receiver's escrow account + function thaw(address receiver, uint256 amount) external; + + // Withdraws all thawed escrow from a receiver's escrow account + function withdraw(address receiver) external; + + // Collect from escrow (up to amount available in escrow) for a receiver using sender's deposit + function collect(address sender, address receiver, uint256 amount) external; +} diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol new file mode 100644 index 000000000..2dc89374a --- /dev/null +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +interface IGraphPayments { + function approveCollector(address dataService) external; + function collect( + address sender, + address receiver, + uint256 amount, + uint256 paymentType, + uint256 dataServiceCut + ) external; +} diff --git a/packages/subgraph-service/lib/forge-std b/packages/subgraph-service/lib/forge-std new file mode 160000 index 000000000..bb4ceea94 --- /dev/null +++ b/packages/subgraph-service/lib/forge-std @@ -0,0 +1 @@ +Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef From ac75c308831f9cd26aff754540ec91196c50301a Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 12 Apr 2024 13:03:58 -0300 Subject: [PATCH 007/277] chore: add comment --- packages/horizon/contracts/interfaces/IGraphPayments.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 2dc89374a..2836844c4 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -2,7 +2,10 @@ pragma solidity ^0.8.24; interface IGraphPayments { + // approve a data service to collect funds function approveCollector(address dataService) external; + + // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( address sender, address receiver, From cb1c50a069adb277db441d36a1ed14cf15992112 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 12 Apr 2024 15:21:48 -0300 Subject: [PATCH 008/277] chore: add GraphPayments interface and data --- packages/horizon/contracts/GraphEscrow.sol | 3 +- .../horizon/contracts/GraphEscrowStorage.sol | 6 +-- packages/horizon/contracts/GraphPayments.sol | 50 +++++++++++++++++++ .../contracts/GraphPaymentsStorage.sol | 19 +++++++ .../contracts/interfaces/IGraphPayments.sol | 18 ++++++- 5 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 packages/horizon/contracts/GraphPayments.sol create mode 100644 packages/horizon/contracts/GraphPaymentsStorage.sol diff --git a/packages/horizon/contracts/GraphEscrow.sol b/packages/horizon/contracts/GraphEscrow.sol index a6a58c7e1..06f6e4b42 100644 --- a/packages/horizon/contracts/GraphEscrow.sol +++ b/packages/horizon/contracts/GraphEscrow.sol @@ -3,10 +3,11 @@ pragma solidity ^0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; -contract GraphEscrow is GraphEscrowStorageV1Storage { +contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage { // -- Errors -- error GraphEscrowNotGraphPayments(); diff --git a/packages/horizon/contracts/GraphEscrowStorage.sol b/packages/horizon/contracts/GraphEscrowStorage.sol index aa8567d8b..472915481 100644 --- a/packages/horizon/contracts/GraphEscrowStorage.sol +++ b/packages/horizon/contracts/GraphEscrowStorage.sol @@ -8,10 +8,10 @@ contract GraphEscrowStorageV1Storage { mapping(address sender => mapping(address receiver => IGraphEscrow.EscrowAccount escrowAccount)) public escrowAccounts; - // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn - uint256 public immutable withdrawEscrowThawingPeriod; - // The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation // This is a precautionary measure to avoid inadvertedly locking funds for too long uint256 public constant MAX_THAWING_PERIOD = 90 days; + + // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn + uint256 public immutable withdrawEscrowThawingPeriod; } diff --git a/packages/horizon/contracts/GraphPayments.sol b/packages/horizon/contracts/GraphPayments.sol new file mode 100644 index 000000000..7131d7abd --- /dev/null +++ b/packages/horizon/contracts/GraphPayments.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; + +import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; +import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; +import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; + +contract GraphEscrow is IGraphPayments, GraphPaymentsStorageV1Storage { + // -- Errors -- + + // -- Immutable variables -- + + IGraphToken public immutable graphToken; + IHorizonStaking public immutable staking; + IGraphEscrow public immutable graphEscrow; + + // -- Modifier -- + + // -- Constructor -- + + constructor(address _graphToken, address _staking, address _graphEscrow) { + graphToken = IGraphToken(_graphToken); + staking = IHorizonStaking(_staking); + graphEscrow = IGraphEscrow(_graphEscrow); + } + + // approve a data service to collect funds + function approveCollector(address dataService) external {} + + // thaw a data service's collector authorization + function thawCollector(address dataService) external {} + + // cancel thawing a data service's collector authorization + function cancelThawCollector(address dataService) external {} + + // revoke authorized collector + function revokeCollector(address dataService) external {} + + // collect funds from a sender, pay cuts and forward the rest to the receiver + function collect( + address sender, + address receiver, + uint256 amount, + uint256 paymentType, + uint256 dataServiceCut + ) external {} +} diff --git a/packages/horizon/contracts/GraphPaymentsStorage.sol b/packages/horizon/contracts/GraphPaymentsStorage.sol new file mode 100644 index 000000000..ebf732f70 --- /dev/null +++ b/packages/horizon/contracts/GraphPaymentsStorage.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; + +contract GraphPaymentsStorageV1Storage { + // Authorized collectors + mapping(address sender => mapping(address collector => uint256 thawEndTimestamp)) public authorizedCollectors; + + // The maximum thawing period (in seconds) for removing collector authorization + // This is a precautionary measure to avoid inadvertedly locking collectors for too long + uint256 public constant MAX_THAWING_PERIOD = 90 days; + + // Thawing period for authorized collectors + uint256 public immutable revokeCollectorThawingPeriod; + + // The graph protocol payment cut + uint256 public immutable protocolPaymentCut; +} diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 2836844c4..b008878fb 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -2,15 +2,31 @@ pragma solidity ^0.8.24; interface IGraphPayments { + // Payment types + enum PaymentType { + Null, + Indexing, + Query + } + // approve a data service to collect funds function approveCollector(address dataService) external; + // thaw a data service's collector authorization + function thawCollector(address dataService) external; + + // cancel thawing a data service's collector authorization + function cancelThawCollector(address dataService) external; + + // revoke authorized collector + function revokeCollector(address dataService) external; + // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( address sender, address receiver, uint256 amount, - uint256 paymentType, + PaymentType paymentType, uint256 dataServiceCut ) external; } From f22adef7046982efbdc5c3633e31a3c164964574 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 12 Apr 2024 18:16:44 -0300 Subject: [PATCH 009/277] chore: implement Escrow deposit --- .../contracts/governance/Controller.sol | 2 +- .../contracts/governance/Governed.sol | 2 +- .../contracts/governance/IController.sol | 2 +- .../contracts/governance/IManaged.sol | 2 +- .../contracts/governance/Managed.sol | 2 +- .../contracts/governance/Pausable.sol | 2 +- .../contracts/contracts/token/IGraphToken.sol | 2 +- packages/horizon/contracts/GraphDirectory.sol | 25 +++++++++ packages/horizon/contracts/GraphEscrow.sol | 20 +++---- packages/horizon/contracts/GraphPayments.sol | 4 +- packages/horizon/contracts/SimpleTest.sol | 10 ---- .../contracts/interfaces/IGraphPayments.sol | 5 +- packages/horizon/lib/forge-std | 2 +- packages/horizon/package.json | 1 + packages/horizon/test/GraphEscrow.t.sol | 54 +++++++++++++++++++ packages/horizon/test/SimpleTest.t.sol | 17 ------ packages/horizon/test/SimpleTest.ts | 23 -------- packages/horizon/test/mocks/MockGRTToken.sol | 46 ++++++++++++++++ yarn.lock | 8 +++ 19 files changed, 157 insertions(+), 72 deletions(-) create mode 100644 packages/horizon/contracts/GraphDirectory.sol delete mode 100644 packages/horizon/contracts/SimpleTest.sol create mode 100644 packages/horizon/test/GraphEscrow.t.sol delete mode 100644 packages/horizon/test/SimpleTest.t.sol delete mode 100644 packages/horizon/test/SimpleTest.ts create mode 100644 packages/horizon/test/mocks/MockGRTToken.sol diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index affb29a05..2f3654109 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; import { IController } from "./IController.sol"; import { IManaged } from "./IManaged.sol"; diff --git a/packages/contracts/contracts/governance/Governed.sol b/packages/contracts/contracts/governance/Governed.sol index f692b2d19..9902eafc9 100644 --- a/packages/contracts/contracts/governance/Governed.sol +++ b/packages/contracts/contracts/governance/Governed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; /** * @title Graph Governance contract diff --git a/packages/contracts/contracts/governance/IController.sol b/packages/contracts/contracts/governance/IController.sol index 7df3d94ee..0549c723d 100644 --- a/packages/contracts/contracts/governance/IController.sol +++ b/packages/contracts/contracts/governance/IController.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.8.0; +pragma solidity >=0.6.12 <0.9.0; interface IController { function getGovernor() external view returns (address); diff --git a/packages/contracts/contracts/governance/IManaged.sol b/packages/contracts/contracts/governance/IManaged.sol index 76f05e0fb..4cedf9c0b 100644 --- a/packages/contracts/contracts/governance/IManaged.sol +++ b/packages/contracts/contracts/governance/IManaged.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; import { IController } from "./IController.sol"; diff --git a/packages/contracts/contracts/governance/Managed.sol b/packages/contracts/contracts/governance/Managed.sol index fb65e71b9..f0172dc94 100644 --- a/packages/contracts/contracts/governance/Managed.sol +++ b/packages/contracts/contracts/governance/Managed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; import { IController } from "./IController.sol"; diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 552b0aa15..5ff29c19e 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; abstract contract Pausable { /** diff --git a/packages/contracts/contracts/token/IGraphToken.sol b/packages/contracts/contracts/token/IGraphToken.sol index 8255e18d5..f24467d42 100644 --- a/packages/contracts/contracts/token/IGraphToken.sol +++ b/packages/contracts/contracts/token/IGraphToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.7.6 <=0.9.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/packages/horizon/contracts/GraphDirectory.sol b/packages/horizon/contracts/GraphDirectory.sol new file mode 100644 index 000000000..d229bd0c4 --- /dev/null +++ b/packages/horizon/contracts/GraphDirectory.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +pragma solidity 0.8.24; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; +import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; + +contract GraphDirectory { + IController public immutable graphController; + IHorizonStaking public immutable graphStaking; + IGraphToken public immutable graphToken; + IGraphEscrow public immutable graphEscrow; + IGraphPayments public immutable graphPayments; + + constructor(address _controller) { + graphController = IController(_controller); + graphStaking = IHorizonStaking(graphController.getContractProxy(keccak256("Staking"))); + graphToken = IGraphToken(graphController.getContractProxy(keccak256("GraphToken"))); + graphEscrow = IGraphEscrow(graphController.getContractProxy(keccak256("GraphEscrow"))); + graphPayments = IGraphPayments(graphController.getContractProxy(keccak256("GraphPayments"))); + } +} diff --git a/packages/horizon/contracts/GraphEscrow.sol b/packages/horizon/contracts/GraphEscrow.sol index 06f6e4b42..b2acd630c 100644 --- a/packages/horizon/contracts/GraphEscrow.sol +++ b/packages/horizon/contracts/GraphEscrow.sol @@ -5,17 +5,17 @@ import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToke import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; +import { GraphDirectory } from "./GraphDirectory.sol"; import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; -contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage { +contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirectory { // -- Errors -- error GraphEscrowNotGraphPayments(); - // -- Immutable variables -- + // -- Events -- - IGraphToken public immutable graphToken; - IGraphPayments public immutable graphPayments; + event Deposit(address indexed sender, address indexed receiver, uint256 amount); // -- Modifier -- @@ -28,14 +28,16 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage { // -- Constructor -- - constructor(address _graphToken, address _graphPayments, uint256 _withdrawEscrowThawingPeriod) { - graphToken = IGraphToken(_graphToken); - graphPayments = IGraphPayments(_graphPayments); - _withdrawEscrowThawingPeriod = _withdrawEscrowThawingPeriod; + constructor(address _controller, uint256 _withdrawEscrowThawingPeriod) GraphDirectory(_controller) { + withdrawEscrowThawingPeriod = _withdrawEscrowThawingPeriod; } // Deposit funds into the escrow for a receiver - function deposit(address receiver, uint256 amount) external {} + function deposit(address receiver, uint256 amount) external { + escrowAccounts[msg.sender][receiver].balance += amount; + graphToken.transferFrom(msg.sender, address(this), amount); + emit Deposit(msg.sender, receiver, amount); + } // Deposit funds into the escrow for multiple receivers function depositMany(address[] calldata receivers, uint256[] calldata amounts) external {} diff --git a/packages/horizon/contracts/GraphPayments.sol b/packages/horizon/contracts/GraphPayments.sol index 7131d7abd..6990518d3 100644 --- a/packages/horizon/contracts/GraphPayments.sol +++ b/packages/horizon/contracts/GraphPayments.sol @@ -8,7 +8,7 @@ import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; -contract GraphEscrow is IGraphPayments, GraphPaymentsStorageV1Storage { +contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage { // -- Errors -- // -- Immutable variables -- @@ -44,7 +44,7 @@ contract GraphEscrow is IGraphPayments, GraphPaymentsStorageV1Storage { address sender, address receiver, uint256 amount, - uint256 paymentType, + IGraphPayments.PaymentType paymentType, uint256 dataServiceCut ) external {} } diff --git a/packages/horizon/contracts/SimpleTest.sol b/packages/horizon/contracts/SimpleTest.sol deleted file mode 100644 index 5cc28d9cc..000000000 --- a/packages/horizon/contracts/SimpleTest.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.4.0 <0.9.0; - -import { Test } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; - -contract SimpleTest is Test { - function test() external pure returns (uint256) { - return 42; - } -} diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index b008878fb..ebc05ef34 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -4,9 +4,8 @@ pragma solidity ^0.8.24; interface IGraphPayments { // Payment types enum PaymentType { - Null, - Indexing, - Query + IndexingFees, + QueryFees } // approve a data service to collect funds diff --git a/packages/horizon/lib/forge-std b/packages/horizon/lib/forge-std index bb4ceea94..e4aef94c1 160000 --- a/packages/horizon/lib/forge-std +++ b/packages/horizon/lib/forge-std @@ -1 +1 @@ -Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef +Subproject commit e4aef94c1768803a16fe19f7ce8b65defd027cfd diff --git a/packages/horizon/package.json b/packages/horizon/package.json index ec23f62cb..59dcaee89 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -20,6 +20,7 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.0", "@nomicfoundation/hardhat-toolbox": "^4.0.0", "@nomicfoundation/hardhat-verify": "^2.0.0", + "@openzeppelin/contracts": "^5.0.2", "@typechain/ethers-v6": "^0.5.0", "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol new file mode 100644 index 000000000..2f77dbfbc --- /dev/null +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; + +import { GraphEscrow } from "contracts/GraphEscrow.sol"; +import { GraphPayments } from "contracts/GraphPayments.sol"; + +import "./mocks/MockGRTToken.sol"; + +contract GraphEscrowTest is Test { + GraphEscrow escrow; + + Controller controller; + MockGRTToken token; + + address governor = address(0xA1); + uint256 initialSupply = 1000000 ether; + uint256 withdrawEscrowThawingPeriod = 60; + + address sender; + address receiver; + + // Setup + + function setUp() public { + vm.prank(governor); + controller = new Controller(); + token = new MockGRTToken(); + + vm.startPrank(governor); + controller.setContractProxy(keccak256("GraphToken"), address(token)); + vm.stopPrank(); + + escrow = new GraphEscrow(address(controller), withdrawEscrowThawingPeriod); + + sender = address(0xB1); + receiver = address(0xB2); + } + + function testDeposit() public { + token.mint(sender, 10000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + vm.stopPrank(); + + + (uint256 receiverEscrowBalance,,) = escrow.escrowAccounts(sender, receiver); + assertEq(receiverEscrowBalance, 1000 ether); + } +} \ No newline at end of file diff --git a/packages/horizon/test/SimpleTest.t.sol b/packages/horizon/test/SimpleTest.t.sol deleted file mode 100644 index b130e5d34..000000000 --- a/packages/horizon/test/SimpleTest.t.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.10; - -import "forge-std/Test.sol"; -import { SimpleTest } from "../contracts/SimpleTest.sol"; - -contract ContractTest is Test { - SimpleTest simpleTest; - - function setUp() public { - simpleTest = new SimpleTest(); - } - - function test_NumberIs42() public { - assertEq(simpleTest.test(), 42); - } -} diff --git a/packages/horizon/test/SimpleTest.ts b/packages/horizon/test/SimpleTest.ts deleted file mode 100644 index cfcfb1443..000000000 --- a/packages/horizon/test/SimpleTest.ts +++ /dev/null @@ -1,23 +0,0 @@ -import hardhat from 'hardhat' - -import { expect } from 'chai' -import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' - -const ethers = hardhat.ethers - -describe('SimpleTest', function () { - async function deployFixture() { - const [owner] = await ethers.getSigners() - const SimpleTest = await ethers.getContractFactory('SimpleTest') - const simpleTest = await SimpleTest.deploy() - return { simpleTest, owner } - } - - describe('Deployment', function () { - it('Should return 42', async function () { - const { simpleTest } = await loadFixture(deployFixture) - - expect(await simpleTest.test()).to.equal(42) - }) - }) -}) diff --git a/packages/horizon/test/mocks/MockGRTToken.sol b/packages/horizon/test/mocks/MockGRTToken.sol new file mode 100644 index 000000000..11cf5c0f8 --- /dev/null +++ b/packages/horizon/test/mocks/MockGRTToken.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; + +contract MockGRTToken is ERC20, IGraphToken { + constructor() ERC20("Graph Token", "GRT") {} + + function burn(uint256 amount) external {} + + function burnFrom(address _from, uint256 amount) external { + _burn(_from, amount); + } + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } + + // -- Mint Admin -- + + function addMinter(address _account) external {} + + function removeMinter(address _account) external {} + + function renounceMinter() external {} + + function isMinter(address _account) external view returns (bool) {} + + // -- Permit -- + + function permit( + address _owner, + address _spender, + uint256 _value, + uint256 _deadline, + uint8 _v, + bytes32 _r, + bytes32 _s + ) external {} + + // -- Allowance -- + + function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {} + function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 27dfd84b0..00e728326 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2935,6 +2935,7 @@ __metadata: "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0" "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" "@nomicfoundation/hardhat-verify": "npm:^2.0.0" + "@openzeppelin/contracts": "npm:^5.0.2" "@typechain/ethers-v6": "npm:^0.5.0" "@typechain/hardhat": "npm:^9.0.0" "@types/chai": "npm:^4.2.0" @@ -5044,6 +5045,13 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts@npm:^5.0.2": + version: 5.0.2 + resolution: "@openzeppelin/contracts@npm:5.0.2" + checksum: d042661db7bb2f3a4b9ef30bba332e86ac20907d171f2ebfccdc9255cc69b62786fead8d6904b8148a8f26946bc7c15eead91b95f75db0c193a99d52e528663e + languageName: node + linkType: hard + "@openzeppelin/defender-admin-client@npm:^1.46.0": version: 1.54.1 resolution: "@openzeppelin/defender-admin-client@npm:1.54.1" From 7f1431cceaae1b1aec77546794aff8cd476ac468 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 17 Apr 2024 12:26:10 -0300 Subject: [PATCH 010/277] chore: add GraphEscrow implementation --- packages/horizon/contracts/GraphEscrow.sol | 96 +++++++++++++++++++++- packages/horizon/test/GraphEscrow.t.sol | 72 +++++++++++++++- 2 files changed, 163 insertions(+), 5 deletions(-) diff --git a/packages/horizon/contracts/GraphEscrow.sol b/packages/horizon/contracts/GraphEscrow.sol index b2acd630c..afb23d97b 100644 --- a/packages/horizon/contracts/GraphEscrow.sol +++ b/packages/horizon/contracts/GraphEscrow.sol @@ -12,10 +12,25 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector // -- Errors -- error GraphEscrowNotGraphPayments(); + error GraphEscrowInputsLengthMismatch(); + error GraphEscrowInsufficientThawAmount(); + error GraphEscrowInsufficientAmount(uint256 available, uint256 required); + error GraphEscrowNotThawing(); + error GraphEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); // -- Events -- event Deposit(address indexed sender, address indexed receiver, uint256 amount); + event CancelThaw(address indexed sender, address indexed receiver); + event Thaw( + address indexed sender, + address indexed receiver, + uint256 amount, + uint256 totalAmountThawing, + uint256 thawEndTimestamp + ); + event Withdraw(address indexed sender, address indexed receiver, uint256 amount); + event Collect(address indexed sender, address indexed receiver, uint256 amount); // -- Modifier -- @@ -40,14 +55,87 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector } // Deposit funds into the escrow for multiple receivers - function depositMany(address[] calldata receivers, uint256[] calldata amounts) external {} + function depositMany(address[] calldata receivers, uint256[] calldata amounts) external { + if (receivers.length != amounts.length) { + revert GraphEscrowInputsLengthMismatch(); + } + + uint256 totalAmount = 0; + for (uint256 i = 0; i < receivers.length; i++) { + address receiver = receivers[i]; + uint256 amount = amounts[i]; + + totalAmount += amount; + escrowAccounts[msg.sender][receiver].balance += amount; + emit Deposit(msg.sender, receiver, amount); + } + + graphToken.transferFrom(msg.sender, address(this), totalAmount); + } // Requests to thaw a specific amount of escrow from a receiver's escrow account - function thaw(address receiver, uint256 amount) external {} + function thaw(address receiver, uint256 amount) external { + EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; + if (amount == 0) { + // if amount thawing is zero and requested amount is zero this is an invalid request. + // otherwise if amount thawing is greater than zero and requested amount is zero this + // is a cancel thaw request. + if (account.amountThawing == 0) { + revert GraphEscrowInsufficientThawAmount(); + } + account.amountThawing = 0; + account.thawEndTimestamp = 0; + emit CancelThaw(msg.sender, receiver); + return; + } + + // Check if the escrow balance is sufficient + if (account.balance < amount) { + revert GraphEscrowInsufficientAmount({ available: account.balance, required: amount }); + } + + // Set amount to thaw + account.amountThawing = amount; + // Set when the thaw is complete (thawing period number of seconds after current timestamp) + account.thawEndTimestamp = block.timestamp + withdrawEscrowThawingPeriod; + + emit Thaw(msg.sender, receiver, amount, account.amountThawing, account.thawEndTimestamp); + } // Withdraws all thawed escrow from a receiver's escrow account - function withdraw(address receiver) external {} + function withdraw(address receiver) external { + EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; + if (account.thawEndTimestamp == 0) { + revert GraphEscrowNotThawing(); + } + + if (account.thawEndTimestamp > block.timestamp) { + revert GraphEscrowStillThawing({ + currentTimestamp: block.timestamp, + thawEndTimestamp: account.thawEndTimestamp + }); + } + + // Amount is the minimum between the amount being thawed and the actual balance + uint256 amount = account.amountThawing > account.balance ? account.balance : account.amountThawing; + + account.balance -= amount; // Reduce the balance by the withdrawn amount (no underflow risk) + account.amountThawing = 0; + account.thawEndTimestamp = 0; + graphToken.transfer(msg.sender, amount); + emit Withdraw(msg.sender, receiver, amount); + } // Collect from escrow (up to amount available in escrow) for a receiver using sender's deposit - function collect(address sender, address receiver, uint256 amount) external onlyGraphPayments {} + function collect(address sender, address receiver, uint256 amount) external onlyGraphPayments { + EscrowAccount storage account = escrowAccounts[sender][receiver]; + uint256 available = account.balance - account.amountThawing; + + // TODO: should we revert if not enough funds are available? + uint256 collectAmount = amount > available ? available : amount; + + account.balance -= collectAmount; + graphToken.transfer(msg.sender, collectAmount); + emit Collect(sender, receiver, collectAmount); + } } diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol index 2f77dbfbc..662b30d64 100644 --- a/packages/horizon/test/GraphEscrow.t.sol +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -15,8 +15,9 @@ contract GraphEscrowTest is Test { Controller controller; MockGRTToken token; + address graphPayments = address(0xA1); - address governor = address(0xA1); + address governor = address(0xA2); uint256 initialSupply = 1000000 ether; uint256 withdrawEscrowThawingPeriod = 60; @@ -32,6 +33,7 @@ contract GraphEscrowTest is Test { vm.startPrank(governor); controller.setContractProxy(keccak256("GraphToken"), address(token)); + controller.setContractProxy(keccak256("GraphPayments"), graphPayments); vm.stopPrank(); escrow = new GraphEscrow(address(controller), withdrawEscrowThawingPeriod); @@ -47,8 +49,76 @@ contract GraphEscrowTest is Test { escrow.deposit(receiver, 1000 ether); vm.stopPrank(); + (uint256 receiverEscrowBalance,,) = escrow.escrowAccounts(sender, receiver); + assertEq(receiverEscrowBalance, 1000 ether); + } + + function testDepositMany() public { + address otherReceiver = address(0xB3); + address[] memory receivers = new address[](2); + receivers[0] = receiver; + receivers[1] = otherReceiver; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000 ether; + amounts[1] = 2000 ether; + + token.mint(sender, 3000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 3000 ether); + escrow.depositMany(receivers, amounts); + vm.stopPrank(); (uint256 receiverEscrowBalance,,) = escrow.escrowAccounts(sender, receiver); assertEq(receiverEscrowBalance, 1000 ether); + + (uint256 otherReceiverEscrowBalance,,) = escrow.escrowAccounts(sender, otherReceiver); + assertEq(otherReceiverEscrowBalance, 2000 ether); + } + + function testThaw() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + escrow.thaw(receiver, 100 ether); + vm.stopPrank(); + + (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(sender, receiver); + assertEq(amountThawing, 100 ether); + assertEq(thawEndTimestamp, block.timestamp + withdrawEscrowThawingPeriod); + } + + function testWithdraw() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + escrow.thaw(receiver, 100 ether); + + // advance time + skip(withdrawEscrowThawingPeriod + 1); + + escrow.withdraw(receiver); + vm.stopPrank(); + + (uint256 receiverEscrowBalance,,) = escrow.escrowAccounts(sender, receiver); + assertEq(receiverEscrowBalance, 900 ether); + } + + function testCollect() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + vm.stopPrank(); + + vm.prank(graphPayments); + escrow.collect(sender, receiver, 100 ether); + + (uint256 receiverEscrowBalance,,) = escrow.escrowAccounts(sender, receiver); + assertEq(receiverEscrowBalance, 900 ether); + uint256 graphPaymentsBalance = token.balanceOf(graphPayments); + assertEq(graphPaymentsBalance, 100 ether); } } \ No newline at end of file From 30bbbc6b39cdf77e1055b5e9b3eda1b9103670f4 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 18 Apr 2024 13:56:41 -0300 Subject: [PATCH 011/277] chore: add GraphPayments implementation --- .../contracts/staking/IHorizonStaking.sol | 2 + packages/horizon/contracts/GraphPayments.sol | 91 ++++++++++-- .../contracts/GraphPaymentsStorage.sol | 3 +- .../contracts/interfaces/IGraphPayments.sol | 6 + packages/horizon/foundry.toml | 3 +- packages/horizon/test/GraphDeployments.t.sol | 87 ++++++++++++ packages/horizon/test/GraphEscrow.t.sol | 1 - packages/horizon/test/GraphPayments.t.sol | 133 ++++++++++++++++++ .../horizon/test/mocks/MockHorizonStaking.sol | 43 ++++++ 9 files changed, 351 insertions(+), 18 deletions(-) create mode 100644 packages/horizon/test/GraphDeployments.t.sol create mode 100644 packages/horizon/test/GraphPayments.t.sol create mode 100644 packages/horizon/test/mocks/MockHorizonStaking.sol diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol index a4101ff52..f6bf1dd87 100644 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ b/packages/contracts/contracts/staking/IHorizonStaking.sol @@ -146,4 +146,6 @@ interface IHorizonStaking { function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); function getProvision(bytes32 provision) external view returns (Provision memory); + + function getDelegatorCut(address serviceProvider, uint256256 paymentType) external returns (address, uint256); } diff --git a/packages/horizon/contracts/GraphPayments.sol b/packages/horizon/contracts/GraphPayments.sol index 6990518d3..93c80c7bc 100644 --- a/packages/horizon/contracts/GraphPayments.sol +++ b/packages/horizon/contracts/GraphPayments.sol @@ -6,45 +6,106 @@ import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHor import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; +import { GraphDirectory } from "./GraphDirectory.sol"; import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; -contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage { +contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { // -- Errors -- - // -- Immutable variables -- + error GraphPaymentsNotThawing(); + error GraphPaymentsStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); + error GraphPaymentsCollectorNotAuthorized(address sender, address dataService); - IGraphToken public immutable graphToken; - IHorizonStaking public immutable staking; - IGraphEscrow public immutable graphEscrow; + // -- Events -- + + event AuthorizedCollector(address indexed sender, address indexed dataService); + event ThawCollector(address indexed sender, address indexed dataService); + event CancelThawCollector(address indexed sender, address indexed dataService); + event RevokeCollector(address indexed sender, address indexed dataService); // -- Modifier -- + // -- Parameters -- + + uint256 private immutable MAX_PPM = 1000000; // 100% in parts per million + // -- Constructor -- - constructor(address _graphToken, address _staking, address _graphEscrow) { - graphToken = IGraphToken(_graphToken); - staking = IHorizonStaking(_staking); - graphEscrow = IGraphEscrow(_graphEscrow); + constructor( + address _controller, + uint256 _revokeCollectorThawingPeriod, + uint256 _protocolPaymentCut + ) GraphDirectory(_controller) { + revokeCollectorThawingPeriod = _revokeCollectorThawingPeriod; + protocolPaymentCut = _protocolPaymentCut; } // approve a data service to collect funds - function approveCollector(address dataService) external {} + function approveCollector(address dataService) external { + authorizedCollectors[msg.sender][dataService].authorized = true; + emit AuthorizedCollector(msg.sender, dataService); + } // thaw a data service's collector authorization - function thawCollector(address dataService) external {} + function thawCollector(address dataService) external { + authorizedCollectors[msg.sender][dataService].thawEndTimestamp = block.timestamp + revokeCollectorThawingPeriod; + emit ThawCollector(msg.sender, dataService); + } // cancel thawing a data service's collector authorization - function cancelThawCollector(address dataService) external {} + function cancelThawCollector(address dataService) external { + authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; + emit CancelThawCollector(msg.sender, dataService); + } // revoke authorized collector - function revokeCollector(address dataService) external {} + function revokeCollector(address dataService) external { + Collector storage collector = authorizedCollectors[msg.sender][dataService]; + + if (collector.thawEndTimestamp == 0) { + revert GraphPaymentsNotThawing(); + } + + if (collector.thawEndTimestamp > block.timestamp) { + revert GraphPaymentsStillThawing(block.timestamp, collector.thawEndTimestamp); + } + + delete authorizedCollectors[msg.sender][dataService]; + emit RevokeCollector(msg.sender, dataService); + } // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( address sender, - address receiver, + address receiver, // serviceProvider uint256 amount, IGraphPayments.PaymentType paymentType, uint256 dataServiceCut - ) external {} + ) external { + Collector storage collector = authorizedCollectors[sender][msg.sender]; + + if (!collector.authorized) { + revert GraphPaymentsCollectorNotAuthorized(sender, msg.sender); + } + + // Collect tokens from GraphEscrow + graphEscrow.collect(sender, receiver, amount); + + // Pay protocol cut + uint256 protocolCut = (amount * protocolPaymentCut) / MAX_PPM; + graphToken.burn(protocolCut); + + // Pay data service cut + uint256 dataServicePayment = (amount * dataServiceCut) / MAX_PPM; + graphToken.transfer(msg.sender, dataServicePayment); + + // Get delegation cut + (address delegatorAddress, uint256 delegatorCut) = graphStaking.getDelegatorCut(receiver, uint256256(paymentType)); + uint256 delegatorPayment = (amount * delegatorCut) / MAX_PPM; + graphToken.transfer(delegatorAddress, delegatorPayment); + + // Pay the rest to the receiver + uint256 receiverPayment = amount - protocolCut - dataServicePayment - delegatorPayment; + graphToken.transfer(receiver, receiverPayment); + } } diff --git a/packages/horizon/contracts/GraphPaymentsStorage.sol b/packages/horizon/contracts/GraphPaymentsStorage.sol index ebf732f70..e649aea0c 100644 --- a/packages/horizon/contracts/GraphPaymentsStorage.sol +++ b/packages/horizon/contracts/GraphPaymentsStorage.sol @@ -5,7 +5,8 @@ import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; contract GraphPaymentsStorageV1Storage { // Authorized collectors - mapping(address sender => mapping(address collector => uint256 thawEndTimestamp)) public authorizedCollectors; + mapping(address sender => mapping(address dataService => IGraphPayments.Collector collector)) + public authorizedCollectors; // The maximum thawing period (in seconds) for removing collector authorization // This is a precautionary measure to avoid inadvertedly locking collectors for too long diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index ebc05ef34..5d5fe4ca9 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -8,6 +8,12 @@ interface IGraphPayments { QueryFees } + // Authorized collector + struct Collector { + bool authorized; + uint256 thawEndTimestamp; + } + // approve a data service to collect funds function approveCollector(address dataService) external; diff --git a/packages/horizon/foundry.toml b/packages/horizon/foundry.toml index 55f7ffd31..3582d5476 100644 --- a/packages/horizon/foundry.toml +++ b/packages/horizon/foundry.toml @@ -3,4 +3,5 @@ src = 'contracts' out = 'build' libs = ['node_modules', 'lib'] test = 'test' -cache_path = 'cache_forge' \ No newline at end of file +cache_path = 'cache_forge' +fs_permissions = [{ access = "read", path = "./"}] \ No newline at end of file diff --git a/packages/horizon/test/GraphDeployments.t.sol b/packages/horizon/test/GraphDeployments.t.sol new file mode 100644 index 000000000..2b4a1af2f --- /dev/null +++ b/packages/horizon/test/GraphDeployments.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; + +import { GraphEscrow } from "contracts/GraphEscrow.sol"; +import { GraphPayments } from "contracts/GraphPayments.sol"; +import { IGraphPayments } from "contracts/interfaces/IGraphPayments.sol"; + +import "./mocks/MockHorizonStaking.sol"; +import "./mocks/MockGRTToken.sol"; + +contract GraphDeployments is Test { + Controller public controller; + MockGRTToken public token; + GraphPayments public payments; + GraphEscrow public escrow; + MockHorizonStaking public staking; + + address public governor = address(0x4b39f53A1084b3eC5f2dA8f3B616D11317572efE); + address public deployer = address(0x54705f06556182AeFfFe40386E85D3921c236f78); + + // GraphEscrow parameters + + uint256 public withdrawEscrowThawingPeriod = 60; + + // GraphPayments parameters + + uint256 public revokeCollectorThawingPeriod = 60; + uint256 public protocolPaymentCut = 10000; // 1% + + // Staking parameters + + address public delegatorAddress = address(0xbdC1c9f94A729E47d6877217eC995916EAD457B7); + uint256 public delegatorCut = 50000; // 5% + + // Setup + + constructor() { + setUp(); + } + + function setUp() public { + vm.prank(governor); + controller = new Controller(); + + // GraphPayments preddict address + bytes32 saltPayments = keccak256("GraphPaymentsSalt"); + bytes32 paymentsHash = keccak256(bytes.concat(vm.getCode("GraphPayments.sol:GraphPayments"), abi.encode(address(controller), revokeCollectorThawingPeriod, protocolPaymentCut))); + address predictedPaymentsAddress = vm.computeCreate2Address(saltPayments, paymentsHash, deployer); + + // GraphEscrow preddict address + bytes32 saltEscrow = keccak256("GraphEscrowSalt"); + bytes32 escrowHash = keccak256(bytes.concat(vm.getCode("GraphEscrow.sol:GraphEscrow"), abi.encode(address(controller), withdrawEscrowThawingPeriod))); + address predictedAddressEscrow = vm.computeCreate2Address(saltEscrow, escrowHash, deployer); + + // GraphToken + vm.prank(deployer); + token = new MockGRTToken(); + + // HorizonStaking + vm.prank(deployer); + staking = new MockHorizonStaking(delegatorAddress, delegatorCut); + + // Setup controller + vm.startPrank(governor); + controller.setContractProxy(keccak256("GraphToken"), address(token)); + controller.setContractProxy(keccak256("GraphEscrow"), predictedAddressEscrow); + controller.setContractProxy(keccak256("GraphPayments"), predictedPaymentsAddress); + controller.setContractProxy(keccak256("Staking"), address(staking)); + vm.stopPrank(); + + vm.startPrank(deployer); + payments = new GraphPayments{salt: saltPayments}(address(controller), revokeCollectorThawingPeriod, protocolPaymentCut); + escrow = new GraphEscrow{salt: saltEscrow}(address(controller), withdrawEscrowThawingPeriod); + vm.stopPrank(); + } + + // Tests + + function testDeployments() public view { + assertEq(address(escrow.graphPayments()), address(payments)); + assertEq(address(payments.graphEscrow()), address(escrow)); + } +} \ No newline at end of file diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol index 662b30d64..9ba34820d 100644 --- a/packages/horizon/test/GraphEscrow.t.sol +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -18,7 +18,6 @@ contract GraphEscrowTest is Test { address graphPayments = address(0xA1); address governor = address(0xA2); - uint256 initialSupply = 1000000 ether; uint256 withdrawEscrowThawingPeriod = 60; address sender; diff --git a/packages/horizon/test/GraphPayments.t.sol b/packages/horizon/test/GraphPayments.t.sol new file mode 100644 index 000000000..b97b3b2bf --- /dev/null +++ b/packages/horizon/test/GraphPayments.t.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; + +import { GraphEscrow } from "contracts/GraphEscrow.sol"; +import { GraphPayments } from "contracts/GraphPayments.sol"; +import { IGraphPayments } from "contracts/interfaces/IGraphPayments.sol"; + +import "./GraphDeployments.t.sol"; +import "./mocks/MockGRTToken.sol"; + +contract GraphPaymentsTest is Test { + GraphDeployments deployments; + GraphPayments payments; + Controller controller; + MockGRTToken token; + GraphEscrow escrow; + + address governor; + + uint256 revokeCollectorThawingPeriod; + uint256 protocolPaymentCut; + + address delegatorAddress; + uint256 delegatorCut; + + address sender; + address dataService; + + // Setup + + function setUp() public { + deployments = new GraphDeployments(); + + payments = deployments.payments(); + controller = deployments.controller(); + token = deployments.token(); + escrow = deployments.escrow(); + governor = deployments.governor(); + + revokeCollectorThawingPeriod = deployments.revokeCollectorThawingPeriod(); + protocolPaymentCut = deployments.protocolPaymentCut(); + + delegatorAddress = deployments.delegatorAddress(); + delegatorCut = deployments.delegatorCut(); + + sender = address(0xA1); + dataService = address(0xA2); + } + + // Tests + + function testApproveCollector() public { + vm.prank(sender); + payments.approveCollector(dataService); + + (bool authorized, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + assertEq(authorized, true); + assertEq(thawEndTimestamp, 0); + } + + function testThawCollector() public { + vm.startPrank(sender); + payments.approveCollector(dataService); + payments.thawCollector(dataService); + vm.stopPrank(); + + (bool authorized, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + assertEq(authorized, true); + assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + } + + function testCancelThawCollector() public { + vm.startPrank(sender); + payments.approveCollector(dataService); + payments.thawCollector(dataService); + vm.stopPrank(); + + (bool authorized, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + assertEq(authorized, true); + assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + + vm.prank(sender); + payments.cancelThawCollector(dataService); + + (authorized, thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + assertEq(authorized, true); + assertEq(thawEndTimestamp, 0); + } + + function testRevokeCollector() public { + vm.startPrank(sender); + payments.approveCollector(dataService); + payments.thawCollector(dataService); + skip(revokeCollectorThawingPeriod + 1); + payments.revokeCollector(dataService); + vm.stopPrank(); + + (bool authorized,) = payments.authorizedCollectors(sender, dataService); + assertEq(authorized, false); + } + + function testCollect() public { + vm.prank(sender); + payments.approveCollector(dataService); + + address indexer = address(0xA3); + uint256 amount = 1000 ether; + + token.mint(sender, amount); + vm.startPrank(sender); + token.approve(address(escrow), amount); + escrow.deposit(indexer, amount); + vm.stopPrank(); + + vm.startPrank(dataService); + uint256 dataServiceCut = 30000; // 3% + payments.collect(sender, indexer, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + vm.stopPrank(); + + uint256 indexerBalance = token.balanceOf(indexer); + assertEq(indexerBalance, 910 ether); + + uint256 dataServiceBalance = token.balanceOf(dataService); + assertEq(dataServiceBalance, 30 ether); + + uint256 delegatorBalance = token.balanceOf(delegatorAddress); + assertEq(delegatorBalance, 50 ether); + } +} \ No newline at end of file diff --git a/packages/horizon/test/mocks/MockHorizonStaking.sol b/packages/horizon/test/mocks/MockHorizonStaking.sol new file mode 100644 index 000000000..40eed6a4e --- /dev/null +++ b/packages/horizon/test/mocks/MockHorizonStaking.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { MockGRTToken } from "./MockGRTToken.sol"; + +contract MockHorizonStaking is IHorizonStaking { + address public delegatorAddress; + uint256 public delegatorCut; + + constructor(address _delegatorAddress, uint256 _delegatorCut) { + delegatorAddress = _delegatorAddress; + delegatorCut = _delegatorCut; + } + + function allowVerifier(address verifier, bool allow) external {} + function stake(uint256 tokens) external {} + function provision(uint256 tokens, address verifier, uint256 maxVerifierCut, uint256 thawingPeriod) external {} + function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId) {} + function deprovision(bytes32 thawRequestId) external {} + function reprovision(bytes32 thawRequestId, bytes32 provisionId) external {} + function withdraw(bytes32 thawRequestId) external {} + function delegate(address serviceProvider, uint256 tokens) external {} + function undelegate( + address serviceProvider, + uint256 tokens, + bytes32[] calldata provisions + ) external returns (bytes32 thawRequestId) {} + function slash(bytes32 provisionId, uint256 tokens, uint256 verifierAmount) external {} + function setForceThawProvisions(bytes32[] calldata provisions) external {} + function getStake(address serviceProvider) external view returns (uint256 tokens) {} + function getIdleStake(address serviceProvider) external view returns (uint256 tokens) {} + function getCapacity(address serviceProvider) external view returns (uint256 tokens) {} + function getTokensAvailable(bytes32 provision) external view returns (uint256 tokens) {} + function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory) {} + function getProvision(bytes32 provision) external view returns (Provision memory) {} + + function getDelegatorCut(address serviceProvider, uint paymentType) external returns (address, uint256) { + return (delegatorAddress, delegatorCut); + } +} \ No newline at end of file From 9b6ed9bcfd20b3707a518921af0dcf0e34ddf245 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 18 Apr 2024 16:46:54 -0300 Subject: [PATCH 012/277] chore: use GraphDeployments on GraphEscrow --- packages/horizon/contracts/GraphPayments.sol | 2 +- packages/horizon/test/GraphEscrow.t.sol | 21 ++++++++++--------- .../horizon/test/mocks/MockHorizonStaking.sol | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/horizon/contracts/GraphPayments.sol b/packages/horizon/contracts/GraphPayments.sol index 93c80c7bc..df51dc6f7 100644 --- a/packages/horizon/contracts/GraphPayments.sol +++ b/packages/horizon/contracts/GraphPayments.sol @@ -100,7 +100,7 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi graphToken.transfer(msg.sender, dataServicePayment); // Get delegation cut - (address delegatorAddress, uint256 delegatorCut) = graphStaking.getDelegatorCut(receiver, uint256256(paymentType)); + (address delegatorAddress, uint256 delegatorCut) = graphStaking.getDelegatorCut(receiver, uint256(paymentType)); uint256 delegatorPayment = (amount * delegatorCut) / MAX_PPM; graphToken.transfer(delegatorAddress, delegatorPayment); diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol index 9ba34820d..ae8814971 100644 --- a/packages/horizon/test/GraphEscrow.t.sol +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -8,14 +8,15 @@ import { Controller } from "@graphprotocol/contracts/contracts/governance/Contro import { GraphEscrow } from "contracts/GraphEscrow.sol"; import { GraphPayments } from "contracts/GraphPayments.sol"; +import "./GraphDeployments.t.sol"; import "./mocks/MockGRTToken.sol"; contract GraphEscrowTest is Test { + GraphDeployments deployments; GraphEscrow escrow; - Controller controller; MockGRTToken token; - address graphPayments = address(0xA1); + GraphPayments payments; address governor = address(0xA2); uint256 withdrawEscrowThawingPeriod = 60; @@ -26,16 +27,15 @@ contract GraphEscrowTest is Test { // Setup function setUp() public { - vm.prank(governor); - controller = new Controller(); - token = new MockGRTToken(); + deployments = new GraphDeployments(); - vm.startPrank(governor); - controller.setContractProxy(keccak256("GraphToken"), address(token)); - controller.setContractProxy(keccak256("GraphPayments"), graphPayments); - vm.stopPrank(); + controller = deployments.controller(); + token = deployments.token(); + escrow = deployments.escrow(); + payments = deployments.payments(); - escrow = new GraphEscrow(address(controller), withdrawEscrowThawingPeriod); + governor = deployments.governor(); + withdrawEscrowThawingPeriod = deployments.withdrawEscrowThawingPeriod(); sender = address(0xB1); receiver = address(0xB2); @@ -112,6 +112,7 @@ contract GraphEscrowTest is Test { escrow.deposit(receiver, 1000 ether); vm.stopPrank(); + address graphPayments = address(payments); vm.prank(graphPayments); escrow.collect(sender, receiver, 100 ether); diff --git a/packages/horizon/test/mocks/MockHorizonStaking.sol b/packages/horizon/test/mocks/MockHorizonStaking.sol index 40eed6a4e..0d97d0a72 100644 --- a/packages/horizon/test/mocks/MockHorizonStaking.sol +++ b/packages/horizon/test/mocks/MockHorizonStaking.sol @@ -37,7 +37,7 @@ contract MockHorizonStaking is IHorizonStaking { function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory) {} function getProvision(bytes32 provision) external view returns (Provision memory) {} - function getDelegatorCut(address serviceProvider, uint paymentType) external returns (address, uint256) { + function getDelegatorCut(address serviceProvider, uint256 paymentType) external returns (address, uint256) { return (delegatorAddress, delegatorCut); } } \ No newline at end of file From 76539f7b20f018297bc58f5005567d73201e20fe Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 19 Apr 2024 15:40:16 -0300 Subject: [PATCH 013/277] fix: change staking interface --- .../contracts/contracts/staking/IHorizonStaking.sol | 2 +- packages/horizon/contracts/GraphPayments.sol | 6 ++++-- .../horizon/contracts/interfaces/IGraphPayments.sol | 2 +- packages/horizon/test/GraphDeployments.t.sol | 3 +-- packages/horizon/test/GraphPayments.t.sol | 11 +++-------- packages/horizon/test/mocks/MockHorizonStaking.sol | 8 +++----- 6 files changed, 13 insertions(+), 19 deletions(-) diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol index f6bf1dd87..ed9751696 100644 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ b/packages/contracts/contracts/staking/IHorizonStaking.sol @@ -147,5 +147,5 @@ interface IHorizonStaking { function getProvision(bytes32 provision) external view returns (Provision memory); - function getDelegatorCut(address serviceProvider, uint256256 paymentType) external returns (address, uint256); + function getDelegatorCut(address serviceProvider, uint256 paymentType) external returns (uint256 delegatorCut); } diff --git a/packages/horizon/contracts/GraphPayments.sol b/packages/horizon/contracts/GraphPayments.sol index df51dc6f7..3d9091b4a 100644 --- a/packages/horizon/contracts/GraphPayments.sol +++ b/packages/horizon/contracts/GraphPayments.sol @@ -100,9 +100,11 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi graphToken.transfer(msg.sender, dataServicePayment); // Get delegation cut - (address delegatorAddress, uint256 delegatorCut) = graphStaking.getDelegatorCut(receiver, uint256(paymentType)); + uint256 delegatorCut = graphStaking.getDelegatorCut(receiver, uint256(paymentType)); uint256 delegatorPayment = (amount * delegatorCut) / MAX_PPM; - graphToken.transfer(delegatorAddress, delegatorPayment); + // TODO: Add to delegation pool + // graphStaking.addToDelegationPool(receiver, delegatorPayment); + graphToken.burn(delegatorPayment); // Pay the rest to the receiver uint256 receiverPayment = amount - protocolCut - dataServicePayment - delegatorPayment; diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 5d5fe4ca9..34dc48770 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -8,7 +8,7 @@ interface IGraphPayments { QueryFees } - // Authorized collector + // Collector struct Collector { bool authorized; uint256 thawEndTimestamp; diff --git a/packages/horizon/test/GraphDeployments.t.sol b/packages/horizon/test/GraphDeployments.t.sol index 2b4a1af2f..c0e1abf5a 100644 --- a/packages/horizon/test/GraphDeployments.t.sol +++ b/packages/horizon/test/GraphDeployments.t.sol @@ -33,7 +33,6 @@ contract GraphDeployments is Test { // Staking parameters - address public delegatorAddress = address(0xbdC1c9f94A729E47d6877217eC995916EAD457B7); uint256 public delegatorCut = 50000; // 5% // Setup @@ -62,7 +61,7 @@ contract GraphDeployments is Test { // HorizonStaking vm.prank(deployer); - staking = new MockHorizonStaking(delegatorAddress, delegatorCut); + staking = new MockHorizonStaking(delegatorCut); // Setup controller vm.startPrank(governor); diff --git a/packages/horizon/test/GraphPayments.t.sol b/packages/horizon/test/GraphPayments.t.sol index b97b3b2bf..b96aac1a9 100644 --- a/packages/horizon/test/GraphPayments.t.sol +++ b/packages/horizon/test/GraphPayments.t.sol @@ -24,9 +24,6 @@ contract GraphPaymentsTest is Test { uint256 revokeCollectorThawingPeriod; uint256 protocolPaymentCut; - address delegatorAddress; - uint256 delegatorCut; - address sender; address dataService; @@ -44,9 +41,6 @@ contract GraphPaymentsTest is Test { revokeCollectorThawingPeriod = deployments.revokeCollectorThawingPeriod(); protocolPaymentCut = deployments.protocolPaymentCut(); - delegatorAddress = deployments.delegatorAddress(); - delegatorCut = deployments.delegatorCut(); - sender = address(0xA1); dataService = address(0xA2); } @@ -127,7 +121,8 @@ contract GraphPaymentsTest is Test { uint256 dataServiceBalance = token.balanceOf(dataService); assertEq(dataServiceBalance, 30 ether); - uint256 delegatorBalance = token.balanceOf(delegatorAddress); - assertEq(delegatorBalance, 50 ether); + // TODO: test delegator cut payment + // uint256 delegatorBalance = token.balanceOf(delegationPool); + // assertEq(delegatorBalance, 50 ether); } } \ No newline at end of file diff --git a/packages/horizon/test/mocks/MockHorizonStaking.sol b/packages/horizon/test/mocks/MockHorizonStaking.sol index 0d97d0a72..a71beff98 100644 --- a/packages/horizon/test/mocks/MockHorizonStaking.sol +++ b/packages/horizon/test/mocks/MockHorizonStaking.sol @@ -7,11 +7,9 @@ import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHor import { MockGRTToken } from "./MockGRTToken.sol"; contract MockHorizonStaking is IHorizonStaking { - address public delegatorAddress; uint256 public delegatorCut; - constructor(address _delegatorAddress, uint256 _delegatorCut) { - delegatorAddress = _delegatorAddress; + constructor(uint256 _delegatorCut) { delegatorCut = _delegatorCut; } @@ -37,7 +35,7 @@ contract MockHorizonStaking is IHorizonStaking { function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory) {} function getProvision(bytes32 provision) external view returns (Provision memory) {} - function getDelegatorCut(address serviceProvider, uint256 paymentType) external returns (address, uint256) { - return (delegatorAddress, delegatorCut); + function getDelegatorCut(address serviceProvider, uint256 paymentType) external returns (uint256) { + return delegatorCut; } } \ No newline at end of file From 914f65faf4e487475fedfc9111e13757d73005f4 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 19 Apr 2024 16:15:54 -0300 Subject: [PATCH 014/277] chore: use addToDelegationPool --- .../contracts/staking/IHorizonStaking.sol | 3 ++- packages/horizon/contracts/GraphPayments.sol | 6 ++---- packages/horizon/test/GraphDeployments.t.sol | 4 ++-- packages/horizon/test/GraphPayments.t.sol | 8 +++++--- .../horizon/test/mocks/MockHorizonStaking.sol | 16 ++++++++++------ 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol index ed9751696..d55520db5 100644 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ b/packages/contracts/contracts/staking/IHorizonStaking.sol @@ -147,5 +147,6 @@ interface IHorizonStaking { function getProvision(bytes32 provision) external view returns (Provision memory); - function getDelegatorCut(address serviceProvider, uint256 paymentType) external returns (uint256 delegatorCut); + function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256 delegationCut); + function addToDelegationPool(address serviceProvider, uint256 tokens) external; } diff --git a/packages/horizon/contracts/GraphPayments.sol b/packages/horizon/contracts/GraphPayments.sol index 3d9091b4a..553f5b7ce 100644 --- a/packages/horizon/contracts/GraphPayments.sol +++ b/packages/horizon/contracts/GraphPayments.sol @@ -100,11 +100,9 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi graphToken.transfer(msg.sender, dataServicePayment); // Get delegation cut - uint256 delegatorCut = graphStaking.getDelegatorCut(receiver, uint256(paymentType)); + uint256 delegatorCut = graphStaking.getDelegationCut(receiver, uint8(paymentType)); uint256 delegatorPayment = (amount * delegatorCut) / MAX_PPM; - // TODO: Add to delegation pool - // graphStaking.addToDelegationPool(receiver, delegatorPayment); - graphToken.burn(delegatorPayment); + graphStaking.addToDelegationPool(receiver, delegatorPayment); // Pay the rest to the receiver uint256 receiverPayment = amount - protocolCut - dataServicePayment - delegatorPayment; diff --git a/packages/horizon/test/GraphDeployments.t.sol b/packages/horizon/test/GraphDeployments.t.sol index c0e1abf5a..490445f5b 100644 --- a/packages/horizon/test/GraphDeployments.t.sol +++ b/packages/horizon/test/GraphDeployments.t.sol @@ -33,7 +33,7 @@ contract GraphDeployments is Test { // Staking parameters - uint256 public delegatorCut = 50000; // 5% + uint256 public delegationCut = 50000; // 5% // Setup @@ -61,7 +61,7 @@ contract GraphDeployments is Test { // HorizonStaking vm.prank(deployer); - staking = new MockHorizonStaking(delegatorCut); + staking = new MockHorizonStaking(delegationCut); // Setup controller vm.startPrank(governor); diff --git a/packages/horizon/test/GraphPayments.t.sol b/packages/horizon/test/GraphPayments.t.sol index b96aac1a9..ea9585db0 100644 --- a/packages/horizon/test/GraphPayments.t.sol +++ b/packages/horizon/test/GraphPayments.t.sol @@ -10,6 +10,7 @@ import { GraphPayments } from "contracts/GraphPayments.sol"; import { IGraphPayments } from "contracts/interfaces/IGraphPayments.sol"; import "./GraphDeployments.t.sol"; +import "./mocks/MockHorizonStaking.sol"; import "./mocks/MockGRTToken.sol"; contract GraphPaymentsTest is Test { @@ -18,6 +19,7 @@ contract GraphPaymentsTest is Test { Controller controller; MockGRTToken token; GraphEscrow escrow; + MockHorizonStaking staking; address governor; @@ -36,6 +38,7 @@ contract GraphPaymentsTest is Test { controller = deployments.controller(); token = deployments.token(); escrow = deployments.escrow(); + staking = deployments.staking(); governor = deployments.governor(); revokeCollectorThawingPeriod = deployments.revokeCollectorThawingPeriod(); @@ -121,8 +124,7 @@ contract GraphPaymentsTest is Test { uint256 dataServiceBalance = token.balanceOf(dataService); assertEq(dataServiceBalance, 30 ether); - // TODO: test delegator cut payment - // uint256 delegatorBalance = token.balanceOf(delegationPool); - // assertEq(delegatorBalance, 50 ether); + uint256 delegatorBalance = staking.delegationPool(indexer); + assertEq(delegatorBalance, 50 ether); } } \ No newline at end of file diff --git a/packages/horizon/test/mocks/MockHorizonStaking.sol b/packages/horizon/test/mocks/MockHorizonStaking.sol index a71beff98..a31cc8798 100644 --- a/packages/horizon/test/mocks/MockHorizonStaking.sol +++ b/packages/horizon/test/mocks/MockHorizonStaking.sol @@ -4,13 +4,13 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; -import { MockGRTToken } from "./MockGRTToken.sol"; contract MockHorizonStaking is IHorizonStaking { - uint256 public delegatorCut; + uint256 public delegationCut; + mapping(address serviceProvider => uint256 tokens) public delegationPool; - constructor(uint256 _delegatorCut) { - delegatorCut = _delegatorCut; + constructor(uint256 _delegationCut) { + delegationCut = _delegationCut; } function allowVerifier(address verifier, bool allow) external {} @@ -35,7 +35,11 @@ contract MockHorizonStaking is IHorizonStaking { function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory) {} function getProvision(bytes32 provision) external view returns (Provision memory) {} - function getDelegatorCut(address serviceProvider, uint256 paymentType) external returns (uint256) { - return delegatorCut; + function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256) { + return delegationCut; + } + + function addToDelegationPool(address serviceProvider, uint256 tokens) external { + delegationPool[serviceProvider] += tokens; } } \ No newline at end of file From 575faec3008230ccf744178550b0f64b6591cb22 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 19 Apr 2024 16:34:09 -0300 Subject: [PATCH 015/277] chore: move files to folders --- packages/horizon/contracts/{ => escrow}/GraphEscrow.sol | 6 +++--- .../horizon/contracts/{ => escrow}/GraphEscrowStorage.sol | 2 +- packages/horizon/contracts/{ => payments}/GraphPayments.sol | 6 +++--- .../contracts/{ => payments}/GraphPaymentsStorage.sol | 2 +- packages/horizon/test/GraphDeployments.t.sol | 4 ++-- packages/horizon/test/GraphEscrow.t.sol | 4 ++-- packages/horizon/test/GraphPayments.t.sol | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) rename packages/horizon/contracts/{ => escrow}/GraphEscrow.sol (96%) rename packages/horizon/contracts/{ => escrow}/GraphEscrowStorage.sol (92%) rename packages/horizon/contracts/{ => payments}/GraphPayments.sol (95%) rename packages/horizon/contracts/{ => payments}/GraphPaymentsStorage.sol (91%) diff --git a/packages/horizon/contracts/GraphEscrow.sol b/packages/horizon/contracts/escrow/GraphEscrow.sol similarity index 96% rename from packages/horizon/contracts/GraphEscrow.sol rename to packages/horizon/contracts/escrow/GraphEscrow.sol index afb23d97b..dd4d2e9c3 100644 --- a/packages/horizon/contracts/GraphEscrow.sol +++ b/packages/horizon/contracts/escrow/GraphEscrow.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; -import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; -import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; -import { GraphDirectory } from "./GraphDirectory.sol"; +import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { GraphDirectory } from "../GraphDirectory.sol"; import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirectory { diff --git a/packages/horizon/contracts/GraphEscrowStorage.sol b/packages/horizon/contracts/escrow/GraphEscrowStorage.sol similarity index 92% rename from packages/horizon/contracts/GraphEscrowStorage.sol rename to packages/horizon/contracts/escrow/GraphEscrowStorage.sol index 472915481..1f5657e18 100644 --- a/packages/horizon/contracts/GraphEscrowStorage.sol +++ b/packages/horizon/contracts/escrow/GraphEscrowStorage.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; +import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; contract GraphEscrowStorageV1Storage { // Stores how much escrow each sender has deposited for each receiver, as well as thawing information diff --git a/packages/horizon/contracts/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol similarity index 95% rename from packages/horizon/contracts/GraphPayments.sol rename to packages/horizon/contracts/payments/GraphPayments.sol index 553f5b7ce..5213e3e17 100644 --- a/packages/horizon/contracts/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; -import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; -import { IGraphEscrow } from "./interfaces/IGraphEscrow.sol"; -import { GraphDirectory } from "./GraphDirectory.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; +import { GraphDirectory } from "../GraphDirectory.sol"; import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { diff --git a/packages/horizon/contracts/GraphPaymentsStorage.sol b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol similarity index 91% rename from packages/horizon/contracts/GraphPaymentsStorage.sol rename to packages/horizon/contracts/payments/GraphPaymentsStorage.sol index e649aea0c..4c6051c43 100644 --- a/packages/horizon/contracts/GraphPaymentsStorage.sol +++ b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; contract GraphPaymentsStorageV1Storage { // Authorized collectors diff --git a/packages/horizon/test/GraphDeployments.t.sol b/packages/horizon/test/GraphDeployments.t.sol index 490445f5b..159035101 100644 --- a/packages/horizon/test/GraphDeployments.t.sol +++ b/packages/horizon/test/GraphDeployments.t.sol @@ -5,8 +5,8 @@ import "forge-std/Test.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; -import { GraphEscrow } from "contracts/GraphEscrow.sol"; -import { GraphPayments } from "contracts/GraphPayments.sol"; +import { GraphEscrow } from "contracts/escrow/GraphEscrow.sol"; +import { GraphPayments } from "contracts/payments/GraphPayments.sol"; import { IGraphPayments } from "contracts/interfaces/IGraphPayments.sol"; import "./mocks/MockHorizonStaking.sol"; diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol index ae8814971..5a2f66976 100644 --- a/packages/horizon/test/GraphEscrow.t.sol +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -5,8 +5,8 @@ import "forge-std/Test.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; -import { GraphEscrow } from "contracts/GraphEscrow.sol"; -import { GraphPayments } from "contracts/GraphPayments.sol"; +import { GraphEscrow } from "contracts/escrow/GraphEscrow.sol"; +import { GraphPayments } from "contracts/payments/GraphPayments.sol"; import "./GraphDeployments.t.sol"; import "./mocks/MockGRTToken.sol"; diff --git a/packages/horizon/test/GraphPayments.t.sol b/packages/horizon/test/GraphPayments.t.sol index ea9585db0..a3c77d9c0 100644 --- a/packages/horizon/test/GraphPayments.t.sol +++ b/packages/horizon/test/GraphPayments.t.sol @@ -5,8 +5,8 @@ import "forge-std/Test.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; -import { GraphEscrow } from "contracts/GraphEscrow.sol"; -import { GraphPayments } from "contracts/GraphPayments.sol"; +import { GraphEscrow } from "contracts/escrow/GraphEscrow.sol"; +import { GraphPayments } from "contracts/payments/GraphPayments.sol"; import { IGraphPayments } from "contracts/interfaces/IGraphPayments.sol"; import "./GraphDeployments.t.sol"; From e0e93a02f00187f09c6345a9021e31680174a29b Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 19 Apr 2024 17:14:58 -0300 Subject: [PATCH 016/277] chore: add unit tests --- .../contracts/interfaces/IGraphPayments.sol | 3 +- .../contracts/payments/GraphPayments.sol | 15 ++- packages/horizon/test/GraphEscrow.t.sol | 93 +++++++++++++++++++ packages/horizon/test/GraphPayments.t.sol | 91 +++++++++++++++--- 4 files changed, 189 insertions(+), 13 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 34dc48770..29802301b 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -11,11 +11,12 @@ interface IGraphPayments { // Collector struct Collector { bool authorized; + uint256 amount; uint256 thawEndTimestamp; } // approve a data service to collect funds - function approveCollector(address dataService) external; + function approveCollector(address dataService, uint256 amount) external; // thaw a data service's collector authorization function thawCollector(address dataService) external; diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 5213e3e17..67e321fb2 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -15,6 +15,7 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi error GraphPaymentsNotThawing(); error GraphPaymentsStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); error GraphPaymentsCollectorNotAuthorized(address sender, address dataService); + error GraphPaymentsCollectorInsufficientAmount(uint256 available, uint256 required); // -- Events -- @@ -41,8 +42,9 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi } // approve a data service to collect funds - function approveCollector(address dataService) external { + function approveCollector(address dataService, uint256 amount) external { authorizedCollectors[msg.sender][dataService].authorized = true; + authorizedCollectors[msg.sender][dataService].amount = amount; emit AuthorizedCollector(msg.sender, dataService); } @@ -54,6 +56,10 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi // cancel thawing a data service's collector authorization function cancelThawCollector(address dataService) external { + if (authorizedCollectors[msg.sender][dataService].thawEndTimestamp == 0) { + revert GraphPaymentsNotThawing(); + } + authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; emit CancelThawCollector(msg.sender, dataService); } @@ -88,6 +94,13 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi revert GraphPaymentsCollectorNotAuthorized(sender, msg.sender); } + if (collector.amount < amount) { + revert GraphPaymentsCollectorInsufficientAmount(collector.amount, amount); + } + + // Reduce amount from approved collector + collector.amount -= amount; + // Collect tokens from GraphEscrow graphEscrow.collect(sender, receiver, amount); diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol index 5a2f66976..356d4571c 100644 --- a/packages/horizon/test/GraphEscrow.t.sol +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -41,6 +41,8 @@ contract GraphEscrowTest is Test { receiver = address(0xB2); } + // Deposit tests + function testDeposit() public { token.mint(sender, 10000 ether); vm.startPrank(sender); @@ -75,6 +77,27 @@ contract GraphEscrowTest is Test { assertEq(otherReceiverEscrowBalance, 2000 ether); } + function testDepositMany_RevertWhen_InputsLengthMismatch() public { + address otherReceiver = address(0xB3); + address[] memory receivers = new address[](2); + receivers[0] = receiver; + receivers[1] = otherReceiver; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1000 ether; + + token.mint(sender, 1000 ether); + token.approve(address(escrow), 1000 ether); + + // revert + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInputsLengthMismatch()"); + vm.expectRevert(expectedError); + vm.prank(sender); + escrow.depositMany(receivers, amounts); + } + + // Thaw tests + function testThaw() public { token.mint(sender, 1000 ether); vm.startPrank(sender); @@ -88,6 +111,34 @@ contract GraphEscrowTest is Test { assertEq(thawEndTimestamp, block.timestamp + withdrawEscrowThawingPeriod); } + function testThaw_RevertWhen_InsufficientThawAmount() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + + // revert + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientThawAmount()"); + vm.expectRevert(expectedError); + escrow.thaw(receiver, 0); + vm.stopPrank(); + } + + function testThaw_RevertWhen_InsufficientAmount() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + + // revert + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", 1000 ether, 2000 ether); + vm.expectRevert(expectedError); + escrow.thaw(receiver, 2000 ether); + vm.stopPrank(); + } + + // Withdraw tests + function testWithdraw() public { token.mint(sender, 1000 ether); vm.startPrank(sender); @@ -105,6 +156,35 @@ contract GraphEscrowTest is Test { assertEq(receiverEscrowBalance, 900 ether); } + function testWithdraw_RevertWhen_NotThawing() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + + // revert + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + vm.expectRevert(expectedError); + escrow.withdraw(receiver); + vm.stopPrank(); + } + + function testWithdraw_RevertWhen_StillThawing() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + escrow.thaw(receiver, 100 ether); + + // revert + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + withdrawEscrowThawingPeriod); + vm.expectRevert(expectedError); + escrow.withdraw(receiver); + vm.stopPrank(); + } + + // Collect tests + function testCollect() public { token.mint(sender, 1000 ether); vm.startPrank(sender); @@ -121,4 +201,17 @@ contract GraphEscrowTest is Test { uint256 graphPaymentsBalance = token.balanceOf(graphPayments); assertEq(graphPaymentsBalance, 100 ether); } + + function testCollect_RevertWhen_NotGraphPayments() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 1000 ether); + vm.stopPrank(); + + // revert + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotGraphPayments()"); + vm.expectRevert(expectedError); + escrow.collect(sender, receiver, 100 ether); + } } \ No newline at end of file diff --git a/packages/horizon/test/GraphPayments.t.sol b/packages/horizon/test/GraphPayments.t.sol index a3c77d9c0..ec85dd9c3 100644 --- a/packages/horizon/test/GraphPayments.t.sol +++ b/packages/horizon/test/GraphPayments.t.sol @@ -48,61 +48,97 @@ contract GraphPaymentsTest is Test { dataService = address(0xA2); } - // Tests + // Approve tests function testApproveCollector() public { vm.prank(sender); - payments.approveCollector(dataService); + payments.approveCollector(dataService, 1000 ether); - (bool authorized, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + (bool authorized,, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); assertEq(authorized, true); assertEq(thawEndTimestamp, 0); } + // Thaw tests + function testThawCollector() public { vm.startPrank(sender); - payments.approveCollector(dataService); + payments.approveCollector(dataService, 1000 ether); payments.thawCollector(dataService); vm.stopPrank(); - (bool authorized, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + (bool authorized,, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); assertEq(authorized, true); assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); } + // Cancel thaw tests + function testCancelThawCollector() public { vm.startPrank(sender); - payments.approveCollector(dataService); + payments.approveCollector(dataService, 1000 ether); payments.thawCollector(dataService); vm.stopPrank(); - (bool authorized, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + (bool authorized,, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); assertEq(authorized, true); assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); vm.prank(sender); payments.cancelThawCollector(dataService); - (authorized, thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); + (authorized,, thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); assertEq(authorized, true); assertEq(thawEndTimestamp, 0); } + function testCancel_RevertWhen_CollectorIsNotThawing() public { + vm.startPrank(sender); + payments.approveCollector(dataService, 1000 ether); + bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsNotThawing()"); + vm.expectRevert(expectedError); + payments.cancelThawCollector(dataService); + vm.stopPrank(); + } + + // Revoke tests + function testRevokeCollector() public { vm.startPrank(sender); - payments.approveCollector(dataService); + payments.approveCollector(dataService, 1000 ether); payments.thawCollector(dataService); skip(revokeCollectorThawingPeriod + 1); payments.revokeCollector(dataService); vm.stopPrank(); - (bool authorized,) = payments.authorizedCollectors(sender, dataService); + (bool authorized,,) = payments.authorizedCollectors(sender, dataService); assertEq(authorized, false); } + function testRevoke_RevertWhen_CollectorIsNotThawing() public { + vm.startPrank(sender); + payments.approveCollector(dataService, 1000 ether); + bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsNotThawing()"); + vm.expectRevert(expectedError); + payments.revokeCollector(dataService); + vm.stopPrank(); + } + + function testRevoke_RevertWhen_CollectorIsStillThawing() public { + vm.startPrank(sender); + payments.approveCollector(dataService, 1000 ether); + payments.thawCollector(dataService); + bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); + vm.expectRevert(expectedError); + payments.revokeCollector(dataService); + vm.stopPrank(); + } + + // Collect tests + function testCollect() public { vm.prank(sender); - payments.approveCollector(dataService); + payments.approveCollector(dataService, 1000 ether); address indexer = address(0xA3); uint256 amount = 1000 ether; @@ -127,4 +163,37 @@ contract GraphPaymentsTest is Test { uint256 delegatorBalance = staking.delegationPool(indexer); assertEq(delegatorBalance, 50 ether); } + + function testCollect_RevertWhen_CollectorNotAuthorized() public { + address indexer = address(0xA3); + uint256 amount = 1000 ether; + + vm.startPrank(dataService); + uint256 dataServiceCut = 30000; // 3% + bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsCollectorNotAuthorized(address,address)", sender, dataService); + vm.expectRevert(expectedError); + payments.collect(sender, indexer, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + vm.stopPrank(); + } + + function testCollect_RevertWhen_CollectorHasInsufficientAmount() public { + vm.prank(sender); + payments.approveCollector(dataService, 100 ether); + + address indexer = address(0xA3); + uint256 amount = 1000 ether; + + token.mint(sender, amount); + vm.startPrank(sender); + token.approve(address(escrow), amount); + escrow.deposit(indexer, amount); + vm.stopPrank(); + + vm.startPrank(dataService); + uint256 dataServiceCut = 30000; // 3% + bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsCollectorInsufficientAmount(uint256,uint256)", 100 ether, 1000 ether); + vm.expectRevert(expectedError); + payments.collect(sender, indexer, 1000 ether, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + vm.stopPrank(); + } } \ No newline at end of file From 2b7cff58a264bbfd41866e2920320219bc2afe28 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 8 May 2024 18:41:00 -0300 Subject: [PATCH 017/277] chore: move Collector functionality to Escrow, now Escrow calls Payments --- .../horizon/contracts/escrow/GraphEscrow.sol | 107 ++++++++++--- .../contracts/escrow/GraphEscrowStorage.sol | 7 + .../contracts/interfaces/IGraphEscrow.sol | 18 ++- .../contracts/interfaces/IGraphPayments.sol | 23 +-- .../contracts/payments/GraphPayments.sol | 87 ++--------- .../payments/GraphPaymentsStorage.sol | 11 -- .../horizon/contracts/utils/TokenUtils.sol | 42 ++++++ packages/horizon/test/GraphDeployments.t.sol | 8 +- packages/horizon/test/GraphEscrow.t.sol | 139 +++++++++++++++-- packages/horizon/test/GraphPayments.t.sol | 140 +----------------- packages/subgraph-service/lib/forge-std | 1 - 11 files changed, 303 insertions(+), 280 deletions(-) create mode 100644 packages/horizon/contracts/utils/TokenUtils.sol delete mode 160000 packages/subgraph-service/lib/forge-std diff --git a/packages/horizon/contracts/escrow/GraphEscrow.sol b/packages/horizon/contracts/escrow/GraphEscrow.sol index dd4d2e9c3..a1f5c38f0 100644 --- a/packages/horizon/contracts/escrow/GraphEscrow.sol +++ b/packages/horizon/contracts/escrow/GraphEscrow.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; - import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { GraphDirectory } from "../GraphDirectory.sol"; import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; +import { TokenUtils } from "../utils/TokenUtils.sol"; contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirectory { // -- Errors -- @@ -17,9 +16,16 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector error GraphEscrowInsufficientAmount(uint256 available, uint256 required); error GraphEscrowNotThawing(); error GraphEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); + error GraphEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); + error GraphEscrowCollectorNotAuthorized(address sender, address dataService); + error GraphEscrowCollectorInsufficientAmount(uint256 available, uint256 required); // -- Events -- + event AuthorizedCollector(address indexed sender, address indexed dataService); + event ThawCollector(address indexed sender, address indexed dataService); + event CancelThawCollector(address indexed sender, address indexed dataService); + event RevokeCollector(address indexed sender, address indexed dataService); event Deposit(address indexed sender, address indexed receiver, uint256 amount); event CancelThaw(address indexed sender, address indexed receiver); event Thaw( @@ -32,25 +38,68 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector event Withdraw(address indexed sender, address indexed receiver, uint256 amount); event Collect(address indexed sender, address indexed receiver, uint256 amount); - // -- Modifier -- + // -- Constructor -- - modifier onlyGraphPayments() { - if (msg.sender != address(graphPayments)) { - revert GraphEscrowNotGraphPayments(); + constructor( + address _controller, + uint256 _revokeCollectorThawingPeriod, + uint256 _withdrawEscrowThawingPeriod + ) GraphDirectory(_controller) { + if (_revokeCollectorThawingPeriod > MAX_THAWING_PERIOD) { + revert GraphEscrowThawingPeriodTooLong(_revokeCollectorThawingPeriod, MAX_THAWING_PERIOD); } - _; - } - // -- Constructor -- + if (_withdrawEscrowThawingPeriod > MAX_THAWING_PERIOD) { + revert GraphEscrowThawingPeriodTooLong(_withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD); + } - constructor(address _controller, uint256 _withdrawEscrowThawingPeriod) GraphDirectory(_controller) { + revokeCollectorThawingPeriod = _revokeCollectorThawingPeriod; withdrawEscrowThawingPeriod = _withdrawEscrowThawingPeriod; } + // approve a data service to collect funds + function approveCollector(address dataService, uint256 amount) external { + authorizedCollectors[msg.sender][dataService].authorized = true; + authorizedCollectors[msg.sender][dataService].amount = amount; + emit AuthorizedCollector(msg.sender, dataService); + } + + // thaw a data service's collector authorization + function thawCollector(address dataService) external { + authorizedCollectors[msg.sender][dataService].thawEndTimestamp = block.timestamp + revokeCollectorThawingPeriod; + emit ThawCollector(msg.sender, dataService); + } + + // cancel thawing a data service's collector authorization + function cancelThawCollector(address dataService) external { + if (authorizedCollectors[msg.sender][dataService].thawEndTimestamp == 0) { + revert GraphEscrowNotThawing(); + } + + authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; + emit CancelThawCollector(msg.sender, dataService); + } + + // revoke authorized collector + function revokeCollector(address dataService) external { + Collector storage collector = authorizedCollectors[msg.sender][dataService]; + + if (collector.thawEndTimestamp == 0) { + revert GraphEscrowNotThawing(); + } + + if (collector.thawEndTimestamp > block.timestamp) { + revert GraphEscrowStillThawing(block.timestamp, collector.thawEndTimestamp); + } + + delete authorizedCollectors[msg.sender][dataService]; + emit RevokeCollector(msg.sender, dataService); + } + // Deposit funds into the escrow for a receiver function deposit(address receiver, uint256 amount) external { escrowAccounts[msg.sender][receiver].balance += amount; - graphToken.transferFrom(msg.sender, address(this), amount); + TokenUtils.pullTokens(graphToken, msg.sender, amount); emit Deposit(msg.sender, receiver, amount); } @@ -70,7 +119,7 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector emit Deposit(msg.sender, receiver, amount); } - graphToken.transferFrom(msg.sender, address(this), totalAmount); + TokenUtils.pullTokens(graphToken, msg.sender, totalAmount); } // Requests to thaw a specific amount of escrow from a receiver's escrow account @@ -122,20 +171,42 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector account.balance -= amount; // Reduce the balance by the withdrawn amount (no underflow risk) account.amountThawing = 0; account.thawEndTimestamp = 0; - graphToken.transfer(msg.sender, amount); + TokenUtils.pushTokens(graphToken, msg.sender, amount); emit Withdraw(msg.sender, receiver, amount); } // Collect from escrow (up to amount available in escrow) for a receiver using sender's deposit - function collect(address sender, address receiver, uint256 amount) external onlyGraphPayments { + function collect( + address sender, + address receiver, // serviceProvider + address dataService, + uint256 amount, + IGraphPayments.PaymentType paymentType, + uint256 tokensDataService + ) external { + // Check if collector is authorized and has enough funds + Collector storage collector = authorizedCollectors[sender][msg.sender]; + + if (!collector.authorized) { + revert GraphEscrowCollectorNotAuthorized(sender, msg.sender); + } + + if (collector.amount < amount) { + revert GraphEscrowCollectorInsufficientAmount(collector.amount, amount); + } + + // Reduce amount from approved collector + collector.amount -= amount; + + // Collect tokens from GraphEscrow up to amount available EscrowAccount storage account = escrowAccounts[sender][receiver]; uint256 available = account.balance - account.amountThawing; - - // TODO: should we revert if not enough funds are available? uint256 collectAmount = amount > available ? available : amount; - account.balance -= collectAmount; - graphToken.transfer(msg.sender, collectAmount); emit Collect(sender, receiver, collectAmount); + + // Approve tokens so GraphPayments can pull them + graphToken.approve(address(graphPayments), collectAmount); + graphPayments.collect(receiver, dataService, collectAmount, paymentType, tokensDataService); } } diff --git a/packages/horizon/contracts/escrow/GraphEscrowStorage.sol b/packages/horizon/contracts/escrow/GraphEscrowStorage.sol index 1f5657e18..158b7fae0 100644 --- a/packages/horizon/contracts/escrow/GraphEscrowStorage.sol +++ b/packages/horizon/contracts/escrow/GraphEscrowStorage.sol @@ -4,6 +4,10 @@ pragma solidity ^0.8.24; import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; contract GraphEscrowStorageV1Storage { + // Authorized collectors + mapping(address sender => mapping(address dataService => IGraphEscrow.Collector collector)) + public authorizedCollectors; + // Stores how much escrow each sender has deposited for each receiver, as well as thawing information mapping(address sender => mapping(address receiver => IGraphEscrow.EscrowAccount escrowAccount)) public escrowAccounts; @@ -12,6 +16,9 @@ contract GraphEscrowStorageV1Storage { // This is a precautionary measure to avoid inadvertedly locking funds for too long uint256 public constant MAX_THAWING_PERIOD = 90 days; + // Thawing period for authorized collectors + uint256 public immutable revokeCollectorThawingPeriod; + // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn uint256 public immutable withdrawEscrowThawingPeriod; } diff --git a/packages/horizon/contracts/interfaces/IGraphEscrow.sol b/packages/horizon/contracts/interfaces/IGraphEscrow.sol index 8e6ca58fd..841e18eb8 100644 --- a/packages/horizon/contracts/interfaces/IGraphEscrow.sol +++ b/packages/horizon/contracts/interfaces/IGraphEscrow.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; +import { IGraphPayments } from "./IGraphPayments.sol"; + interface IGraphEscrow { struct EscrowAccount { uint256 balance; // Total escrow balance for a sender-receiver pair @@ -8,6 +10,13 @@ interface IGraphEscrow { uint256 thawEndTimestamp; // Timestamp at which thawing period ends (zero if not thawing) } + // Collector + struct Collector { + bool authorized; + uint256 amount; + uint256 thawEndTimestamp; + } + // Deposit funds into the escrow for a receiver function deposit(address receiver, uint256 amount) external; @@ -21,5 +30,12 @@ interface IGraphEscrow { function withdraw(address receiver) external; // Collect from escrow (up to amount available in escrow) for a receiver using sender's deposit - function collect(address sender, address receiver, uint256 amount) external; + function collect( + address sender, + address receiver, + address dataService, + uint256 amount, + IGraphPayments.PaymentType paymentType, + uint256 tokensDataService + ) external; } diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 29802301b..b3af02b20 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -8,31 +8,12 @@ interface IGraphPayments { QueryFees } - // Collector - struct Collector { - bool authorized; - uint256 amount; - uint256 thawEndTimestamp; - } - - // approve a data service to collect funds - function approveCollector(address dataService, uint256 amount) external; - - // thaw a data service's collector authorization - function thawCollector(address dataService) external; - - // cancel thawing a data service's collector authorization - function cancelThawCollector(address dataService) external; - - // revoke authorized collector - function revokeCollector(address dataService) external; - // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( - address sender, address receiver, + address dataService, uint256 amount, PaymentType paymentType, - uint256 dataServiceCut + uint256 tokensDataService ) external; } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 67e321fb2..dc8809630 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; -import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; - import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; -import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; import { GraphDirectory } from "../GraphDirectory.sol"; import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; +import { TokenUtils } from "../utils/TokenUtils.sol"; contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { // -- Errors -- @@ -19,11 +16,6 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi // -- Events -- - event AuthorizedCollector(address indexed sender, address indexed dataService); - event ThawCollector(address indexed sender, address indexed dataService); - event CancelThawCollector(address indexed sender, address indexed dataService); - event RevokeCollector(address indexed sender, address indexed dataService); - // -- Modifier -- // -- Parameters -- @@ -32,85 +24,26 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi // -- Constructor -- - constructor( - address _controller, - uint256 _revokeCollectorThawingPeriod, - uint256 _protocolPaymentCut - ) GraphDirectory(_controller) { - revokeCollectorThawingPeriod = _revokeCollectorThawingPeriod; + constructor(address _controller, uint256 _protocolPaymentCut) GraphDirectory(_controller) { protocolPaymentCut = _protocolPaymentCut; } - // approve a data service to collect funds - function approveCollector(address dataService, uint256 amount) external { - authorizedCollectors[msg.sender][dataService].authorized = true; - authorizedCollectors[msg.sender][dataService].amount = amount; - emit AuthorizedCollector(msg.sender, dataService); - } - - // thaw a data service's collector authorization - function thawCollector(address dataService) external { - authorizedCollectors[msg.sender][dataService].thawEndTimestamp = block.timestamp + revokeCollectorThawingPeriod; - emit ThawCollector(msg.sender, dataService); - } - - // cancel thawing a data service's collector authorization - function cancelThawCollector(address dataService) external { - if (authorizedCollectors[msg.sender][dataService].thawEndTimestamp == 0) { - revert GraphPaymentsNotThawing(); - } - - authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; - emit CancelThawCollector(msg.sender, dataService); - } - - // revoke authorized collector - function revokeCollector(address dataService) external { - Collector storage collector = authorizedCollectors[msg.sender][dataService]; - - if (collector.thawEndTimestamp == 0) { - revert GraphPaymentsNotThawing(); - } - - if (collector.thawEndTimestamp > block.timestamp) { - revert GraphPaymentsStillThawing(block.timestamp, collector.thawEndTimestamp); - } - - delete authorizedCollectors[msg.sender][dataService]; - emit RevokeCollector(msg.sender, dataService); - } - // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( - address sender, address receiver, // serviceProvider + address dataService, uint256 amount, IGraphPayments.PaymentType paymentType, - uint256 dataServiceCut + uint256 tokensDataService ) external { - Collector storage collector = authorizedCollectors[sender][msg.sender]; - - if (!collector.authorized) { - revert GraphPaymentsCollectorNotAuthorized(sender, msg.sender); - } - - if (collector.amount < amount) { - revert GraphPaymentsCollectorInsufficientAmount(collector.amount, amount); - } - - // Reduce amount from approved collector - collector.amount -= amount; - - // Collect tokens from GraphEscrow - graphEscrow.collect(sender, receiver, amount); + TokenUtils.pullTokens(graphToken, msg.sender, amount); // Pay protocol cut - uint256 protocolCut = (amount * protocolPaymentCut) / MAX_PPM; - graphToken.burn(protocolCut); + uint256 tokensProtocol = (amount * protocolPaymentCut) / MAX_PPM; + TokenUtils.burnTokens(graphToken, tokensProtocol); // Pay data service cut - uint256 dataServicePayment = (amount * dataServiceCut) / MAX_PPM; - graphToken.transfer(msg.sender, dataServicePayment); + TokenUtils.pushTokens(graphToken, dataService, tokensDataService); // Get delegation cut uint256 delegatorCut = graphStaking.getDelegationCut(receiver, uint8(paymentType)); @@ -118,7 +51,7 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi graphStaking.addToDelegationPool(receiver, delegatorPayment); // Pay the rest to the receiver - uint256 receiverPayment = amount - protocolCut - dataServicePayment - delegatorPayment; - graphToken.transfer(receiver, receiverPayment); + uint256 receiverPayment = amount - tokensProtocol - tokensDataService - delegatorPayment; + TokenUtils.pushTokens(graphToken, receiver, receiverPayment); } } diff --git a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol index 4c6051c43..7d4c1c338 100644 --- a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol +++ b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol @@ -4,17 +4,6 @@ pragma solidity ^0.8.24; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; contract GraphPaymentsStorageV1Storage { - // Authorized collectors - mapping(address sender => mapping(address dataService => IGraphPayments.Collector collector)) - public authorizedCollectors; - - // The maximum thawing period (in seconds) for removing collector authorization - // This is a precautionary measure to avoid inadvertedly locking collectors for too long - uint256 public constant MAX_THAWING_PERIOD = 90 days; - - // Thawing period for authorized collectors - uint256 public immutable revokeCollectorThawingPeriod; - // The graph protocol payment cut uint256 public immutable protocolPaymentCut; } diff --git a/packages/horizon/contracts/utils/TokenUtils.sol b/packages/horizon/contracts/utils/TokenUtils.sol new file mode 100644 index 000000000..7bb86c491 --- /dev/null +++ b/packages/horizon/contracts/utils/TokenUtils.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; + +library TokenUtils { + /** + * @dev 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 + */ + function pullTokens(IGraphToken _graphToken, address _from, uint256 _amount) internal { + if (_amount > 0) { + require(_graphToken.transferFrom(_from, address(this), _amount), "!transfer"); + } + } + + /** + * @dev 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 + */ + function pushTokens(IGraphToken _graphToken, address _to, uint256 _amount) internal { + if (_amount > 0) { + require(_graphToken.transfer(_to, _amount), "!transfer"); + } + } + + /** + * @dev Burn tokens held by this contract. + * @param _graphToken Token to burn + * @param _amount Amount of tokens to burn + */ + function burnTokens(IGraphToken _graphToken, uint256 _amount) internal { + if (_amount > 0) { + _graphToken.burn(_amount); + } + } +} diff --git a/packages/horizon/test/GraphDeployments.t.sol b/packages/horizon/test/GraphDeployments.t.sol index 159035101..e08986c62 100644 --- a/packages/horizon/test/GraphDeployments.t.sol +++ b/packages/horizon/test/GraphDeployments.t.sol @@ -47,12 +47,12 @@ contract GraphDeployments is Test { // GraphPayments preddict address bytes32 saltPayments = keccak256("GraphPaymentsSalt"); - bytes32 paymentsHash = keccak256(bytes.concat(vm.getCode("GraphPayments.sol:GraphPayments"), abi.encode(address(controller), revokeCollectorThawingPeriod, protocolPaymentCut))); + bytes32 paymentsHash = keccak256(bytes.concat(vm.getCode("GraphPayments.sol:GraphPayments"), abi.encode(address(controller), protocolPaymentCut))); address predictedPaymentsAddress = vm.computeCreate2Address(saltPayments, paymentsHash, deployer); // GraphEscrow preddict address bytes32 saltEscrow = keccak256("GraphEscrowSalt"); - bytes32 escrowHash = keccak256(bytes.concat(vm.getCode("GraphEscrow.sol:GraphEscrow"), abi.encode(address(controller), withdrawEscrowThawingPeriod))); + bytes32 escrowHash = keccak256(bytes.concat(vm.getCode("GraphEscrow.sol:GraphEscrow"), abi.encode(address(controller), revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod))); address predictedAddressEscrow = vm.computeCreate2Address(saltEscrow, escrowHash, deployer); // GraphToken @@ -72,8 +72,8 @@ contract GraphDeployments is Test { vm.stopPrank(); vm.startPrank(deployer); - payments = new GraphPayments{salt: saltPayments}(address(controller), revokeCollectorThawingPeriod, protocolPaymentCut); - escrow = new GraphEscrow{salt: saltEscrow}(address(controller), withdrawEscrowThawingPeriod); + payments = new GraphPayments{salt: saltPayments}(address(controller), protocolPaymentCut); + escrow = new GraphEscrow{salt: saltEscrow}(address(controller), revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod); vm.stopPrank(); } diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol index 356d4571c..b7304d0ad 100644 --- a/packages/horizon/test/GraphEscrow.t.sol +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -7,6 +7,7 @@ import { Controller } from "@graphprotocol/contracts/contracts/governance/Contro import { GraphEscrow } from "contracts/escrow/GraphEscrow.sol"; import { GraphPayments } from "contracts/payments/GraphPayments.sol"; +import { IGraphPayments } from "contracts/interfaces/IGraphPayments.sol"; import "./GraphDeployments.t.sol"; import "./mocks/MockGRTToken.sol"; @@ -20,9 +21,12 @@ contract GraphEscrowTest is Test { address governor = address(0xA2); uint256 withdrawEscrowThawingPeriod = 60; + uint256 revokeCollectorThawingPeriod; address sender; address receiver; + address verifier; + address dataService; // Setup @@ -36,9 +40,98 @@ contract GraphEscrowTest is Test { governor = deployments.governor(); withdrawEscrowThawingPeriod = deployments.withdrawEscrowThawingPeriod(); + revokeCollectorThawingPeriod = deployments.revokeCollectorThawingPeriod(); sender = address(0xB1); receiver = address(0xB2); + verifier = address(0xB3); + dataService = address(0xB4); + } + + // Collector approve tests + + function testApproveCollector() public { + vm.prank(sender); + escrow.approveCollector(verifier, 1000 ether); + + (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(sender, verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, 0); + } + + // Collector thaw tests + + function testThawCollector() public { + vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); + escrow.thawCollector(verifier); + vm.stopPrank(); + + (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(sender, verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + } + + // Collector cancel thaw tests + + function testCancelThawCollector() public { + vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); + escrow.thawCollector(verifier); + vm.stopPrank(); + + (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(sender, verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + + vm.prank(sender); + escrow.cancelThawCollector(verifier); + + (authorized,, thawEndTimestamp) = escrow.authorizedCollectors(sender, verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, 0); + } + + function testCancel_RevertWhen_CollectorIsNotThawing() public { + vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + vm.expectRevert(expectedError); + escrow.cancelThawCollector(verifier); + vm.stopPrank(); + } + + // Collector revoke tests + + function testRevokeCollector() public { + vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); + escrow.thawCollector(verifier); + skip(revokeCollectorThawingPeriod + 1); + escrow.revokeCollector(verifier); + vm.stopPrank(); + + (bool authorized,,) = escrow.authorizedCollectors(sender, verifier); + assertEq(authorized, false); + } + + function testRevoke_RevertWhen_CollectorIsNotThawing() public { + vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + vm.expectRevert(expectedError); + escrow.revokeCollector(verifier); + vm.stopPrank(); + } + + function testRevoke_RevertWhen_CollectorIsStillThawing() public { + vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); + escrow.thawCollector(verifier); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); + vm.expectRevert(expectedError); + escrow.revokeCollector(verifier); + vm.stopPrank(); } // Deposit tests @@ -188,30 +281,48 @@ contract GraphEscrowTest is Test { function testCollect() public { token.mint(sender, 1000 ether); vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); token.approve(address(escrow), 1000 ether); escrow.deposit(receiver, 1000 ether); vm.stopPrank(); - address graphPayments = address(payments); - vm.prank(graphPayments); - escrow.collect(sender, receiver, 100 ether); + vm.prank(verifier); + escrow.collect(sender, receiver, dataService, 100 ether, IGraphPayments.PaymentType.IndexingFees, 3 ether); - (uint256 receiverEscrowBalance,,) = escrow.escrowAccounts(sender, receiver); - assertEq(receiverEscrowBalance, 900 ether); - uint256 graphPaymentsBalance = token.balanceOf(graphPayments); - assertEq(graphPaymentsBalance, 100 ether); + uint256 indexerBalance = token.balanceOf(receiver); + assertEq(indexerBalance, 91 ether); } - function testCollect_RevertWhen_NotGraphPayments() public { - token.mint(sender, 1000 ether); + function testCollect_RevertWhen_CollectorNotAuthorized() public { + address indexer = address(0xA3); + uint256 amount = 1000 ether; + + vm.startPrank(verifier); + uint256 dataServiceCut = 30000; // 3% + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorNotAuthorized(address,address)", sender, verifier); + vm.expectRevert(expectedError); + escrow.collect(sender, indexer, dataService, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + vm.stopPrank(); + } + + function testCollect_RevertWhen_CollectorHasInsufficientAmount() public { + vm.prank(sender); + escrow.approveCollector(verifier, 100 ether); + + address indexer = address(0xA3); + uint256 amount = 1000 ether; + + token.mint(sender, amount); vm.startPrank(sender); - token.approve(address(escrow), 1000 ether); - escrow.deposit(receiver, 1000 ether); + token.approve(address(escrow), amount); + escrow.deposit(indexer, amount); vm.stopPrank(); - // revert - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotGraphPayments()"); + vm.startPrank(verifier); + uint256 dataServiceCut = 30 ether; + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", 100 ether, 1000 ether); vm.expectRevert(expectedError); - escrow.collect(sender, receiver, 100 ether); + escrow.collect(sender, indexer, dataService, 1000 ether, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + vm.stopPrank(); } } \ No newline at end of file diff --git a/packages/horizon/test/GraphPayments.t.sol b/packages/horizon/test/GraphPayments.t.sol index ec85dd9c3..9c0f0ac56 100644 --- a/packages/horizon/test/GraphPayments.t.sol +++ b/packages/horizon/test/GraphPayments.t.sol @@ -23,7 +23,6 @@ contract GraphPaymentsTest is Test { address governor; - uint256 revokeCollectorThawingPeriod; uint256 protocolPaymentCut; address sender; @@ -41,117 +40,25 @@ contract GraphPaymentsTest is Test { staking = deployments.staking(); governor = deployments.governor(); - revokeCollectorThawingPeriod = deployments.revokeCollectorThawingPeriod(); protocolPaymentCut = deployments.protocolPaymentCut(); sender = address(0xA1); dataService = address(0xA2); } - // Approve tests - - function testApproveCollector() public { - vm.prank(sender); - payments.approveCollector(dataService, 1000 ether); - - (bool authorized,, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); - assertEq(authorized, true); - assertEq(thawEndTimestamp, 0); - } - - // Thaw tests - - function testThawCollector() public { - vm.startPrank(sender); - payments.approveCollector(dataService, 1000 ether); - payments.thawCollector(dataService); - vm.stopPrank(); - - (bool authorized,, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); - assertEq(authorized, true); - assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); - } - - // Cancel thaw tests - - function testCancelThawCollector() public { - vm.startPrank(sender); - payments.approveCollector(dataService, 1000 ether); - payments.thawCollector(dataService); - vm.stopPrank(); - - (bool authorized,, uint256 thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); - assertEq(authorized, true); - assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); - - vm.prank(sender); - payments.cancelThawCollector(dataService); - - (authorized,, thawEndTimestamp) = payments.authorizedCollectors(sender, dataService); - assertEq(authorized, true); - assertEq(thawEndTimestamp, 0); - } - - function testCancel_RevertWhen_CollectorIsNotThawing() public { - vm.startPrank(sender); - payments.approveCollector(dataService, 1000 ether); - bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsNotThawing()"); - vm.expectRevert(expectedError); - payments.cancelThawCollector(dataService); - vm.stopPrank(); - } - - // Revoke tests - - function testRevokeCollector() public { - vm.startPrank(sender); - payments.approveCollector(dataService, 1000 ether); - payments.thawCollector(dataService); - skip(revokeCollectorThawingPeriod + 1); - payments.revokeCollector(dataService); - vm.stopPrank(); - - (bool authorized,,) = payments.authorizedCollectors(sender, dataService); - assertEq(authorized, false); - } - - function testRevoke_RevertWhen_CollectorIsNotThawing() public { - vm.startPrank(sender); - payments.approveCollector(dataService, 1000 ether); - bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsNotThawing()"); - vm.expectRevert(expectedError); - payments.revokeCollector(dataService); - vm.stopPrank(); - } - - function testRevoke_RevertWhen_CollectorIsStillThawing() public { - vm.startPrank(sender); - payments.approveCollector(dataService, 1000 ether); - payments.thawCollector(dataService); - bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); - vm.expectRevert(expectedError); - payments.revokeCollector(dataService); - vm.stopPrank(); - } - // Collect tests function testCollect() public { - vm.prank(sender); - payments.approveCollector(dataService, 1000 ether); - address indexer = address(0xA3); uint256 amount = 1000 ether; + address escrowAddress = address(escrow); - token.mint(sender, amount); - vm.startPrank(sender); - token.approve(address(escrow), amount); - escrow.deposit(indexer, amount); - vm.stopPrank(); + vm.startPrank(escrowAddress); + token.mint(escrowAddress, amount); + token.approve(address(payments), amount); - vm.startPrank(dataService); - uint256 dataServiceCut = 30000; // 3% - payments.collect(sender, indexer, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + uint256 dataServiceCut = 30 ether; // 3% + payments.collect(indexer, dataService, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); vm.stopPrank(); uint256 indexerBalance = token.balanceOf(indexer); @@ -163,37 +70,4 @@ contract GraphPaymentsTest is Test { uint256 delegatorBalance = staking.delegationPool(indexer); assertEq(delegatorBalance, 50 ether); } - - function testCollect_RevertWhen_CollectorNotAuthorized() public { - address indexer = address(0xA3); - uint256 amount = 1000 ether; - - vm.startPrank(dataService); - uint256 dataServiceCut = 30000; // 3% - bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsCollectorNotAuthorized(address,address)", sender, dataService); - vm.expectRevert(expectedError); - payments.collect(sender, indexer, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); - vm.stopPrank(); - } - - function testCollect_RevertWhen_CollectorHasInsufficientAmount() public { - vm.prank(sender); - payments.approveCollector(dataService, 100 ether); - - address indexer = address(0xA3); - uint256 amount = 1000 ether; - - token.mint(sender, amount); - vm.startPrank(sender); - token.approve(address(escrow), amount); - escrow.deposit(indexer, amount); - vm.stopPrank(); - - vm.startPrank(dataService); - uint256 dataServiceCut = 30000; // 3% - bytes memory expectedError = abi.encodeWithSignature("GraphPaymentsCollectorInsufficientAmount(uint256,uint256)", 100 ether, 1000 ether); - vm.expectRevert(expectedError); - payments.collect(sender, indexer, 1000 ether, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); - vm.stopPrank(); - } -} \ No newline at end of file +} diff --git a/packages/subgraph-service/lib/forge-std b/packages/subgraph-service/lib/forge-std deleted file mode 160000 index bb4ceea94..000000000 --- a/packages/subgraph-service/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef From 9ab94292be001e97f1acb7791f205fc8c9049680 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 10 May 2024 14:51:56 -0300 Subject: [PATCH 018/277] chore: revert when there is insufficient amount in deposit --- .../horizon/contracts/escrow/GraphEscrow.sol | 23 +++++++++++++------ .../contracts/interfaces/IGraphEscrow.sol | 4 +++- packages/horizon/test/GraphEscrow.t.sol | 15 ++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/packages/horizon/contracts/escrow/GraphEscrow.sol b/packages/horizon/contracts/escrow/GraphEscrow.sol index a1f5c38f0..2c3e63cc8 100644 --- a/packages/horizon/contracts/escrow/GraphEscrow.sol +++ b/packages/horizon/contracts/escrow/GraphEscrow.sol @@ -175,7 +175,7 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector emit Withdraw(msg.sender, receiver, amount); } - // Collect from escrow (up to amount available in escrow) for a receiver using sender's deposit + // Collect from escrow for a receiver using sender's deposit function collect( address sender, address receiver, // serviceProvider @@ -200,13 +200,22 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector // Collect tokens from GraphEscrow up to amount available EscrowAccount storage account = escrowAccounts[sender][receiver]; - uint256 available = account.balance - account.amountThawing; - uint256 collectAmount = amount > available ? available : amount; - account.balance -= collectAmount; - emit Collect(sender, receiver, collectAmount); + uint256 availableAmount = account.balance - account.amountThawing; + if (availableAmount < amount) { + revert GraphEscrowInsufficientAmount(availableAmount, amount); + } + + account.balance -= amount; + emit Collect(sender, receiver, amount); // Approve tokens so GraphPayments can pull them - graphToken.approve(address(graphPayments), collectAmount); - graphPayments.collect(receiver, dataService, collectAmount, paymentType, tokensDataService); + graphToken.approve(address(graphPayments), amount); + graphPayments.collect(receiver, dataService, amount, paymentType, tokensDataService); + } + + // Get the balance of a sender-receiver pair + function getBalance(address sender, address receiver) external view returns (uint256) { + EscrowAccount storage account = escrowAccounts[sender][receiver]; + return account.balance - account.amountThawing; } } diff --git a/packages/horizon/contracts/interfaces/IGraphEscrow.sol b/packages/horizon/contracts/interfaces/IGraphEscrow.sol index 841e18eb8..f9d3f6140 100644 --- a/packages/horizon/contracts/interfaces/IGraphEscrow.sol +++ b/packages/horizon/contracts/interfaces/IGraphEscrow.sol @@ -29,7 +29,7 @@ interface IGraphEscrow { // Withdraws all thawed escrow from a receiver's escrow account function withdraw(address receiver) external; - // Collect from escrow (up to amount available in escrow) for a receiver using sender's deposit + // Collect from escrow for a receiver using sender's deposit function collect( address sender, address receiver, @@ -38,4 +38,6 @@ interface IGraphEscrow { IGraphPayments.PaymentType paymentType, uint256 tokensDataService ) external; + + function getBalance(address sender, address receiver) external view returns (uint256); } diff --git a/packages/horizon/test/GraphEscrow.t.sol b/packages/horizon/test/GraphEscrow.t.sol index b7304d0ad..221b0f62d 100644 --- a/packages/horizon/test/GraphEscrow.t.sol +++ b/packages/horizon/test/GraphEscrow.t.sol @@ -325,4 +325,19 @@ contract GraphEscrowTest is Test { escrow.collect(sender, indexer, dataService, 1000 ether, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); vm.stopPrank(); } + + function testCollect_RevertWhen_SenderHasInsufficientAmountInEscrow() public { + token.mint(sender, 1000 ether); + vm.startPrank(sender); + escrow.approveCollector(verifier, 1000 ether); + token.approve(address(escrow), 1000 ether); + escrow.deposit(receiver, 100 ether); + vm.stopPrank(); + + vm.prank(verifier); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", 100 ether, 200 ether); + vm.expectRevert(expectedError); + escrow.collect(sender, receiver, dataService, 200 ether, IGraphPayments.PaymentType.IndexingFees, 3 ether); + vm.stopPrank(); + } } \ No newline at end of file From a94a455f474b057f4ea72221713be0e09c300853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Carranza=20V=C3=A9lez?= Date: Fri, 17 May 2024 17:24:20 -0300 Subject: [PATCH 019/277] [WIP] Horizon Staking (#967) * chore(horizon): add staking contract and others (WIP) * chore: fix errors until it compiles * fix: add missing IL2StakingTypes * chore: wip on splitting for code size * chore: somehow it fits in 24kB now * chore: remove global operators and the verifier allowlist * fix: various fixes and a bit of cleanup * chore: slippage protection for delegation * chore: add setter for delegation cuts * chore: add getter for delegation cuts * fix: reintroduce early alloc closure * chore: add support for vesting contracts * fix: various missing things * chore: add OZ contracts * chore: add setOperatorLocked * chore: use delegation ratio in getTokensAvailable * fix: allow changing provision params * fix: remove verifier cut from tokens to slash --- .../contracts/contracts/base/IMulticall.sol | 2 +- .../contracts/contracts/base/Multicall.sol | 2 +- .../contracts/curation/ICuration.sol | 2 +- .../contracts/epochs/IEpochManager.sol | 2 +- .../contracts/gateway/ICallhookReceiver.sol | 2 +- .../contracts/governance/IController.sol | 2 +- .../contracts/governance/IManaged.sol | 2 +- .../contracts/l2/staking/IL2Staking.sol | 20 +- .../contracts/l2/staking/IL2StakingBase.sol | 2 +- .../contracts/l2/staking/IL2StakingTypes.sol | 22 + .../contracts/l2/staking/L2Staking.sol | 23 +- .../contracts/rewards/IRewardsManager.sol | 2 +- .../contracts/staking/IHorizonStaking.sol | 149 --- .../contracts/contracts/staking/L1Staking.sol | 13 +- .../contracts/upgrades/GraphUpgradeable.sol | 2 +- .../contracts/upgrades/IGraphProxy.sol | 2 +- packages/horizon/contracts/GraphDirectory.sol | 34 + packages/horizon/contracts/HorizonStaking.sol | 869 ++++++++++++++++++ .../contracts/HorizonStakingExtension.sol | 262 ++++++ .../contracts/HorizonStakingStorage.sol | 145 +++ packages/horizon/contracts/IGraphToken.sol | 43 + .../horizon/contracts/IHorizonStaking.sol | 9 + .../horizon/contracts/IHorizonStakingBase.sol | 236 +++++ .../contracts/IHorizonStakingExtension.sol | 74 ++ .../contracts/IHorizonStakingTypes.sol | 90 ++ packages/horizon/contracts/IManaged.sol | 25 + .../IStakingBackwardsCompatibility.sol | 189 ++++ packages/horizon/contracts/Managed.sol | 110 +++ packages/horizon/contracts/SimpleTest.sol | 10 - .../StakingBackwardsCompatibility.sol | 508 ++++++++++ .../contracts/mocks/ControllerMock.sol | 125 +++ .../contracts/utils/ExponentialRebates.sol | 64 ++ .../horizon/contracts/utils/LibFixedMath.sol | 389 ++++++++ .../horizon/contracts/utils/MathUtils.sol | 42 + .../horizon/contracts/utils/TokenUtils.sol | 48 + packages/horizon/foundry.toml | 4 +- packages/horizon/hardhat.config.ts | 10 +- packages/horizon/package.json | 3 +- packages/horizon/remappings.txt | 1 + packages/horizon/test/HorizonStaking.t.sol | 35 + packages/horizon/test/HorizonStaking.ts | 38 + packages/horizon/test/SimpleTest.t.sol | 17 - packages/horizon/test/SimpleTest.ts | 23 - yarn.lock | 8 + 44 files changed, 3416 insertions(+), 244 deletions(-) create mode 100644 packages/contracts/contracts/l2/staking/IL2StakingTypes.sol delete mode 100644 packages/contracts/contracts/staking/IHorizonStaking.sol create mode 100644 packages/horizon/contracts/GraphDirectory.sol create mode 100644 packages/horizon/contracts/HorizonStaking.sol create mode 100644 packages/horizon/contracts/HorizonStakingExtension.sol create mode 100644 packages/horizon/contracts/HorizonStakingStorage.sol create mode 100644 packages/horizon/contracts/IGraphToken.sol create mode 100644 packages/horizon/contracts/IHorizonStaking.sol create mode 100644 packages/horizon/contracts/IHorizonStakingBase.sol create mode 100644 packages/horizon/contracts/IHorizonStakingExtension.sol create mode 100644 packages/horizon/contracts/IHorizonStakingTypes.sol create mode 100644 packages/horizon/contracts/IManaged.sol create mode 100644 packages/horizon/contracts/IStakingBackwardsCompatibility.sol create mode 100644 packages/horizon/contracts/Managed.sol delete mode 100644 packages/horizon/contracts/SimpleTest.sol create mode 100644 packages/horizon/contracts/StakingBackwardsCompatibility.sol create mode 100644 packages/horizon/contracts/mocks/ControllerMock.sol create mode 100644 packages/horizon/contracts/utils/ExponentialRebates.sol create mode 100644 packages/horizon/contracts/utils/LibFixedMath.sol create mode 100644 packages/horizon/contracts/utils/MathUtils.sol create mode 100644 packages/horizon/contracts/utils/TokenUtils.sol create mode 100644 packages/horizon/test/HorizonStaking.t.sol create mode 100644 packages/horizon/test/HorizonStaking.ts delete mode 100644 packages/horizon/test/SimpleTest.t.sol delete mode 100644 packages/horizon/test/SimpleTest.ts diff --git a/packages/contracts/contracts/base/IMulticall.sol b/packages/contracts/contracts/base/IMulticall.sol index 3269f694b..65d69d24e 100644 --- a/packages/contracts/contracts/base/IMulticall.sol +++ b/packages/contracts/contracts/base/IMulticall.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; pragma abicoder v2; /** diff --git a/packages/contracts/contracts/base/Multicall.sol b/packages/contracts/contracts/base/Multicall.sol index 49111840d..eff2d3e28 100644 --- a/packages/contracts/contracts/base/Multicall.sol +++ b/packages/contracts/contracts/base/Multicall.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity ^0.7.6 || 0.8.24; pragma abicoder v2; import "./IMulticall.sol"; diff --git a/packages/contracts/contracts/curation/ICuration.sol b/packages/contracts/contracts/curation/ICuration.sol index d92aa9c69..27d37f38c 100644 --- a/packages/contracts/contracts/curation/ICuration.sol +++ b/packages/contracts/contracts/curation/ICuration.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; /** * @title Curation Interface diff --git a/packages/contracts/contracts/epochs/IEpochManager.sol b/packages/contracts/contracts/epochs/IEpochManager.sol index 36b1f47a3..f9a365b9c 100644 --- a/packages/contracts/contracts/epochs/IEpochManager.sol +++ b/packages/contracts/contracts/epochs/IEpochManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; interface IEpochManager { // -- Configuration -- diff --git a/packages/contracts/contracts/gateway/ICallhookReceiver.sol b/packages/contracts/contracts/gateway/ICallhookReceiver.sol index 885b0cdb2..33b06ab5e 100644 --- a/packages/contracts/contracts/gateway/ICallhookReceiver.sol +++ b/packages/contracts/contracts/gateway/ICallhookReceiver.sol @@ -6,7 +6,7 @@ * 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; +pragma solidity >=0.6.12 <0.9.0; interface ICallhookReceiver { /** diff --git a/packages/contracts/contracts/governance/IController.sol b/packages/contracts/contracts/governance/IController.sol index 7df3d94ee..0549c723d 100644 --- a/packages/contracts/contracts/governance/IController.sol +++ b/packages/contracts/contracts/governance/IController.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.8.0; +pragma solidity >=0.6.12 <0.9.0; interface IController { function getGovernor() external view returns (address); diff --git a/packages/contracts/contracts/governance/IManaged.sol b/packages/contracts/contracts/governance/IManaged.sol index 76f05e0fb..4cedf9c0b 100644 --- a/packages/contracts/contracts/governance/IManaged.sol +++ b/packages/contracts/contracts/governance/IManaged.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; import { IController } from "./IController.sol"; diff --git a/packages/contracts/contracts/l2/staking/IL2Staking.sol b/packages/contracts/contracts/l2/staking/IL2Staking.sol index 73ff936ce..4b7748e31 100644 --- a/packages/contracts/contracts/l2/staking/IL2Staking.sol +++ b/packages/contracts/contracts/l2/staking/IL2Staking.sol @@ -5,6 +5,7 @@ pragma abicoder v2; import { IStaking } from "../../staking/IStaking.sol"; import { IL2StakingBase } from "./IL2StakingBase.sol"; +import { IL2StakingTypes } from "./IL2StakingTypes.sol"; /** * @title Interface for the L2 Staking contract @@ -15,21 +16,4 @@ import { IL2StakingBase } from "./IL2StakingBase.sol"; * the custom setup of the Staking contract where part of the functionality is implemented * in a separate contract (StakingExtension) to which calls are delegated through the fallback function. */ -interface IL2Staking is IStaking, IL2StakingBase { - /// @dev Message codes for the L1 -> L2 bridge callhook - enum L1MessageCodes { - RECEIVE_INDEXER_STAKE_CODE, - RECEIVE_DELEGATION_CODE - } - - /// @dev Encoded message struct when receiving indexer stake through the bridge - struct ReceiveIndexerStakeData { - address indexer; - } - - /// @dev Encoded message struct when receiving delegation through the bridge - struct ReceiveDelegationData { - address indexer; - address delegator; - } -} +interface IL2Staking is IStaking, IL2StakingBase, IL2StakingTypes {} diff --git a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol index 6f701ec89..3926dd708 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; diff --git a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol new file mode 100644 index 000000000..41d3fe445 --- /dev/null +++ b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; + +interface IL2StakingTypes { + /// @dev Message codes for the L1 -> L2 bridge callhook + enum L1MessageCodes { + RECEIVE_INDEXER_STAKE_CODE, + RECEIVE_DELEGATION_CODE + } + + /// @dev Encoded message struct when receiving indexer stake through the bridge + struct ReceiveIndexerStakeData { + address indexer; + } + + /// @dev Encoded message struct when receiving delegation through the bridge + struct ReceiveDelegationData { + address indexer; + address delegator; + } +} diff --git a/packages/contracts/contracts/l2/staking/L2Staking.sol b/packages/contracts/contracts/l2/staking/L2Staking.sol index 3f9d28e5a..4bde512ec 100644 --- a/packages/contracts/contracts/l2/staking/L2Staking.sol +++ b/packages/contracts/contracts/l2/staking/L2Staking.sol @@ -8,6 +8,7 @@ import { Staking } from "../../staking/Staking.sol"; import { IL2StakingBase } from "./IL2StakingBase.sol"; import { IL2Staking } from "./IL2Staking.sol"; import { Stakes } from "../../staking/libs/Stakes.sol"; +import { IL2StakingTypes } from "./IL2StakingTypes.sol"; /** * @title L2Staking contract @@ -63,16 +64,16 @@ contract L2Staking is Staking, IL2StakingBase { require(_from == counterpartStakingAddress, "ONLY_L1_STAKING_THROUGH_BRIDGE"); (uint8 code, bytes memory functionData) = abi.decode(_data, (uint8, bytes)); - if (code == uint8(IL2Staking.L1MessageCodes.RECEIVE_INDEXER_STAKE_CODE)) { - IL2Staking.ReceiveIndexerStakeData memory indexerData = abi.decode( + if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_INDEXER_STAKE_CODE)) { + IL2StakingTypes.ReceiveIndexerStakeData memory indexerData = abi.decode( functionData, - (IL2Staking.ReceiveIndexerStakeData) + (IL2StakingTypes.ReceiveIndexerStakeData) ); _receiveIndexerStake(_amount, indexerData); - } else if (code == uint8(IL2Staking.L1MessageCodes.RECEIVE_DELEGATION_CODE)) { - IL2Staking.ReceiveDelegationData memory delegationData = abi.decode( + } else if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE)) { + IL2StakingTypes.ReceiveDelegationData memory delegationData = abi.decode( functionData, - (IL2Staking.ReceiveDelegationData) + (IL2StakingTypes.ReceiveDelegationData) ); _receiveDelegation(_amount, delegationData); } else { @@ -87,7 +88,10 @@ contract L2Staking is Staking, IL2StakingBase { * @param _amount Amount of tokens that were transferred * @param _indexerData struct containing the indexer's address */ - function _receiveIndexerStake(uint256 _amount, IL2Staking.ReceiveIndexerStakeData memory _indexerData) internal { + function _receiveIndexerStake( + uint256 _amount, + IL2StakingTypes.ReceiveIndexerStakeData memory _indexerData + ) internal { address _indexer = _indexerData.indexer; // Deposit tokens into the indexer stake __stakes[_indexer].deposit(_amount); @@ -108,7 +112,10 @@ contract L2Staking is Staking, IL2StakingBase { * @param _amount Amount of tokens that were transferred * @param _delegationData struct containing the delegator's address and the indexer's address */ - function _receiveDelegation(uint256 _amount, IL2Staking.ReceiveDelegationData memory _delegationData) internal { + function _receiveDelegation( + uint256 _amount, + IL2StakingTypes.ReceiveDelegationData memory _delegationData + ) internal { // Get the delegation pool of the indexer DelegationPool storage pool = __delegationPools[_delegationData.indexer]; Delegation storage delegation = pool.delegators[_delegationData.delegator]; diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index 4c062e774..4266a8635 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; interface IRewardsManager { /** diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol deleted file mode 100644 index a4101ff52..000000000 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.7.6 <0.9.0; -pragma abicoder v2; - -interface Test { - function test() external returns (uint256); -} - -interface IHorizonStaking { - struct Provision { - // Service provider that created the provision - address serviceProvider; - // tokens in the provision - uint256 tokens; - // tokens that are being thawed (and will stop being slashable soon) - uint256 tokensThawing; - // timestamp of provision creation - uint64 createdAt; - // authority to slash the provision - address verifier; - // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed - uint32 maxVerifierCut; - // time, in seconds, tokens must thaw before being withdrawn - uint64 thawingPeriod; - } - - // the new "Indexer" struct - struct ServiceProviderInternal { - // Tokens on the Service Provider stake (staked by the provider) - uint256 tokensStaked; - // Tokens used in allocations - uint256 __DEPRECATED_tokensAllocated; - // Tokens locked for withdrawal subject to thawing period - uint256 __DEPRECATED_tokensLocked; - // Block when locked tokens can be withdrawn - uint256 __DEPRECATED_tokensLockedUntil; - // tokens used in a provision - uint256 tokensProvisioned; - // tokens that initiated a thawing in any one of the provider's provisions - uint256 tokensRequestedThaw; - // tokens that have been removed from any one of the provider's provisions after thawing - uint256 tokensFulfilledThaw; - // provisions that take priority for undelegation force thawing - bytes32[] forceThawProvisions; - } - - struct ServiceProvider { - // Tokens on the provider stake (staked by the provider) - uint256 tokensStaked; - // tokens used in a provision - uint256 tokensProvisioned; - // tokens that initiated a thawing in any one of the provider's provisions - uint256 tokensRequestedThaw; - // tokens that have been removed from any one of the provider's provisions after thawing - uint256 tokensFulfilledThaw; - // provisions that take priority for undelegation force thawing - bytes32[] forceThawProvisions; - } - - struct DelegationPool { - uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase - uint32 __DEPRECATED_indexingRewardCut; // in PPM - uint32 __DEPRECATED_queryFeeCut; // in PPM - uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated - uint256 tokens; // Total tokens as pool reserves - uint256 shares; // Total shares minted in the pool - mapping(address => Delegation) delegators; // Mapping of delegator => Delegation - } - - struct Delegation { - // shares owned by the delegator in the pool - uint256 shares; - // tokens delegated to the pool - uint256 tokens; - // Timestamp when locked tokens can be undelegated (after the timelock) - uint256 tokensLockedUntil; - } - - struct ThawRequest { - // tokens that are being thawed by this request - uint256 tokens; - // the provision id to which this request corresponds to - bytes32 provisionId; - // the address that initiated the thaw request, allowed to remove the funds once thawed - address owner; - // the timestamp when the thawed funds can be removed from the provision - uint64 thawingUntil; - // the value of `ServiceProvider.tokensRequestedThaw` the moment the thaw request is created - uint256 tokensRequestedThawSnapshot; - } - - // whitelist/deny a verifier - function allowVerifier(address verifier, bool allow) external; - - // deposit stake - function stake(uint256 tokens) external; - - // create a provision - function provision(uint256 tokens, address verifier, uint256 maxVerifierCut, uint256 thawingPeriod) external; - - // initiate a thawing to remove tokens from a provision - function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId); - - // moves thawed stake from a provision back into the provider's available stake - function deprovision(bytes32 thawRequestId) external; - - // moves thawed stake from one provision into another provision - function reprovision(bytes32 thawRequestId, bytes32 provisionId) external; - - // moves thawed stake back to the owner's account - stake is removed from the protocol - function withdraw(bytes32 thawRequestId) external; - - // delegate tokens to a provider - function delegate(address serviceProvider, uint256 tokens) external; - - // undelegate tokens - function undelegate( - address serviceProvider, - uint256 tokens, - bytes32[] calldata provisions - ) external returns (bytes32 thawRequestId); - - // slash a service provider - function slash(bytes32 provisionId, uint256 tokens, uint256 verifierAmount) external; - - // set the Service Provider's preferred provisions to be force thawed - function setForceThawProvisions(bytes32[] calldata provisions) external; - - // total staked tokens to the provider - // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` - function getStake(address serviceProvider) external view returns (uint256 tokens); - - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) external view returns (uint256 tokens); - - // staked tokens the provider can provision before hitting the delegation cap - // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` - function getCapacity(address serviceProvider) external view returns (uint256 tokens); - - // provisioned tokens that are not being used - // `Provision.tokens - Provision.tokensThawing` - function getTokensAvailable(bytes32 provision) external view returns (uint256 tokens); - - function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); - - function getProvision(bytes32 provision) external view returns (Provision memory); -} diff --git a/packages/contracts/contracts/staking/L1Staking.sol b/packages/contracts/contracts/staking/L1Staking.sol index df4e145bd..5f25cb229 100644 --- a/packages/contracts/contracts/staking/L1Staking.sol +++ b/packages/contracts/contracts/staking/L1Staking.sol @@ -9,12 +9,12 @@ import { ITokenGateway } from "../arbitrum/ITokenGateway.sol"; import { Staking } from "./Staking.sol"; import { Stakes } from "./libs/Stakes.sol"; import { IStakingData } from "./IStakingData.sol"; -import { IL2Staking } from "../l2/staking/IL2Staking.sol"; import { L1StakingV1Storage } from "./L1StakingStorage.sol"; import { IGraphToken } from "../token/IGraphToken.sol"; import { IL1StakingBase } from "./IL1StakingBase.sol"; import { MathUtils } from "./libs/MathUtils.sol"; import { IL1GraphTokenLockTransferTool } from "./IL1GraphTokenLockTransferTool.sol"; +import { IL2StakingTypes } from "../l2/staking/IL2StakingTypes.sol"; /** * @title L1Staking contract @@ -267,11 +267,11 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { ); } - IL2Staking.ReceiveIndexerStakeData memory functionData; + IL2StakingTypes.ReceiveIndexerStakeData memory functionData; functionData.indexer = _l2Beneficiary; bytes memory extraData = abi.encode( - uint8(IL2Staking.L1MessageCodes.RECEIVE_INDEXER_STAKE_CODE), + uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_INDEXER_STAKE_CODE), abi.encode(functionData) ); @@ -324,10 +324,13 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { delegation.shares = 0; bytes memory extraData; { - IL2Staking.ReceiveDelegationData memory functionData; + IL2StakingTypes.ReceiveDelegationData memory functionData; functionData.indexer = indexerTransferredToL2[_indexer]; functionData.delegator = _l2Beneficiary; - extraData = abi.encode(uint8(IL2Staking.L1MessageCodes.RECEIVE_DELEGATION_CODE), abi.encode(functionData)); + extraData = abi.encode( + uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), + abi.encode(functionData) + ); } _sendTokensAndMessageToL2Staking( diff --git a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol index 862f7e7d5..2627e7578 100644 --- a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol +++ b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity ^0.7.6 || 0.8.24; import { IGraphProxy } from "./IGraphProxy.sol"; diff --git a/packages/contracts/contracts/upgrades/IGraphProxy.sol b/packages/contracts/contracts/upgrades/IGraphProxy.sol index 61946e948..cee1aadb0 100644 --- a/packages/contracts/contracts/upgrades/IGraphProxy.sol +++ b/packages/contracts/contracts/upgrades/IGraphProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; interface IGraphProxy { function admin() external returns (address); diff --git a/packages/horizon/contracts/GraphDirectory.sol b/packages/horizon/contracts/GraphDirectory.sol new file mode 100644 index 000000000..dfd9973ea --- /dev/null +++ b/packages/horizon/contracts/GraphDirectory.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; + +/** + * @title GraphDirectory contract + * @notice This contract is meant to be inherited by other contracts that + * need to keep track of the addresses of the core Graph Horizon contracts. + * It fetches the addresses from the Controller supplied during construction, + * and uses immutable variables to minimize gas costs. + */ +contract GraphDirectory { + address public immutable CONTROLLER; + address public immutable STAKING; + address public immutable EPOCH_MANAGER; + address public immutable GRAPH_TOKEN; + address public immutable GRAPH_TOKEN_GATEWAY; + // TODO: also GraphPayments and ScalarEscrow? + // Legacy contracts (pre-Horizon) used for StakingBackwardCompatibility + address public immutable REWARDS_MANAGER; + address public immutable CURATION; + + constructor(address _controller) { + CONTROLLER = _controller; + STAKING = IController(_controller).getContractProxy(keccak256("Staking")); + EPOCH_MANAGER = IController(_controller).getContractProxy(keccak256("EpochManager")); + GRAPH_TOKEN = IController(_controller).getContractProxy(keccak256("GraphToken")); + GRAPH_TOKEN_GATEWAY = IController(_controller).getContractProxy(keccak256("GraphTokenGateway")); + REWARDS_MANAGER = IController(_controller).getContractProxy(keccak256("RewardsManager")); + CURATION = IController(_controller).getContractProxy(keccak256("Curation")); + } +} diff --git a/packages/horizon/contracts/HorizonStaking.sol b/packages/horizon/contracts/HorizonStaking.sol new file mode 100644 index 000000000..7b97260be --- /dev/null +++ b/packages/horizon/contracts/HorizonStaking.sol @@ -0,0 +1,869 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; + +import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; +import { TokenUtils } from "./utils/TokenUtils.sol"; +import { MathUtils } from "./utils/MathUtils.sol"; +import { Managed } from "./Managed.sol"; +import { IGraphToken } from "./IGraphToken.sol"; +import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; + +/** + * @title HorizonStaking contract + * @dev This contract is the main Staking contract in The Graph protocol after the Horizon upgrade. + * It is designed to be deployed as an upgrade to the L2Staking contract from the legacy contracts + * package. + * It uses a HorizonStakingExtension contract to implement the full IHorizonStaking interface through delegatecalls. + * This is due to the contract size limit on Arbitrum (24kB like mainnet). + */ +contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUpgradeable { + /// @dev 100% in parts per million + uint32 internal constant MAX_PPM = 1000000; + + /// @dev Maximum value that can be set as the maxVerifierCut in a provision. + /// It is equivalent to 100% in parts-per-million + uint32 private constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% + + /// @dev Minimum size of a provision + uint256 private constant MIN_PROVISION_SIZE = 1e18; + + /// @dev Maximum number of simultaneous stake thaw requests (per provision) or undelegations (per delegation) + uint256 private constant MAX_THAW_REQUESTS = 100; + + /// @dev Fixed point precision + uint256 private constant FIXED_POINT_PRECISION = 1e18; + + /// @dev Minimum amount of delegation to prevent rounding attacks. + /// TODO: remove this after L2 transfer tool for delegation is removed + /// (delegation on L2 has its own slippage protection) + uint256 private constant MIN_DELEGATION = 1e18; + + address private immutable STAKING_EXTENSION_ADDRESS; + address private immutable SUBGRAPH_DATA_SERVICE_ADDRESS; + + error HorizonStakingInvalidVerifier(address verifier); + error HorizonStakingVerifierAlreadyAllowed(address verifier); + error HorizonStakingVerifierNotAllowed(address verifier); + error HorizonStakingInvalidZeroTokens(); + error HorizonStakingInvalidProvision(address serviceProvider, address verifier); + error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); + error HorizonStakingInsufficientCapacity(); + error HorizonStakingInsufficientShares(); + error HorizonStakingInsufficientCapacityForLegacyAllocations(); + error HorizonStakingTooManyThawRequests(); + error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); + error HorizonStakingSlippageProtection(uint256 minExpectedAmount, uint256 actualAmount); + + modifier onlyAuthorized(address _serviceProvider, address _verifier) { + if (!isAuthorized(msg.sender, _serviceProvider, _verifier)) { + revert HorizonStakingNotAuthorized(msg.sender, _serviceProvider, _verifier); + } + _; + } + + constructor( + address _controller, + address _stakingExtensionAddress, + address _subgraphDataServiceAddress + ) Managed(_controller) { + STAKING_EXTENSION_ADDRESS = _stakingExtensionAddress; + SUBGRAPH_DATA_SERVICE_ADDRESS = _subgraphDataServiceAddress; + } + + /** + * @notice Delegates the current call to the StakingExtension implementation. + * @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 { + //require(_implementation() != address(0), "only through proxy"); + address extensionImpl = STAKING_EXTENSION_ADDRESS; + // solhint-disable-next-line no-inline-assembly + assembly { + // (a) get free memory pointer + let ptr := mload(0x40) + + // (1) copy incoming call data + calldatacopy(ptr, 0, calldatasize()) + + // (2) forward call to logic contract + let result := delegatecall(gas(), extensionImpl, ptr, calldatasize(), 0, 0) + let size := returndatasize() + + // (3) retrieve return data + returndatacopy(ptr, 0, size) + + // (4) forward return data back to caller + switch result + case 0 { + revert(ptr, size) + } + default { + return(ptr, size) + } + } + } + + /** + * @notice Deposit tokens on the caller's stake. + * @param _tokens Amount of tokens to stake + */ + function stake(uint256 _tokens) external override { + stakeTo(msg.sender, _tokens); + } + + /** + * @notice Deposit tokens on the service provider stake, on behalf of the service provider. + * @param _serviceProvider Address of the indexer + * @param _tokens Amount of tokens to stake + */ + function stakeTo(address _serviceProvider, uint256 _tokens) public override notPartialPaused { + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + + // Transfer tokens to stake from caller to this contract + TokenUtils.pullTokens(_graphToken(), msg.sender, _tokens); + + // Stake the transferred tokens + _stake(_serviceProvider, _tokens); + } + + function setProvisionParameters( + address _serviceProvider, + address _verifier, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { + Provision storage prov = provisions[_serviceProvider][_verifier]; + prov.maxVerifierCutPending = _maxVerifierCut; + prov.thawingPeriodPending = _thawingPeriod; + emit ProvisionParametersStaged(_serviceProvider, _verifier, _maxVerifierCut, _thawingPeriod); + } + + function acceptProvisionParameters(address _serviceProvider) external override notPartialPaused { + address verifier = msg.sender; + Provision storage prov = provisions[_serviceProvider][verifier]; + prov.maxVerifierCut = prov.maxVerifierCutPending; + prov.thawingPeriod = prov.thawingPeriodPending; + emit ProvisionParametersSet(_serviceProvider, verifier, prov.maxVerifierCut, prov.thawingPeriod); + } + + /** + * @notice Deposit tokens on the service provider stake, on behalf of the service provider, provisioned + * to a specific verifier. The provider must have previously provisioned stake to that verifier. + * @param _serviceProvider Address of the indexer + * @param _verifier Address of the verifier + * @param _tokens Amount of tokens to stake + */ + function stakeToProvision( + address _serviceProvider, + address _verifier, + uint256 _tokens + ) external override notPartialPaused { + stakeTo(_serviceProvider, _tokens); + _addToProvision(_serviceProvider, _verifier, _tokens); + } + + /** + * @notice Provision stake to a verifier. The tokens will be locked with a thawing period + * and will be slashable by the verifier. This is the main mechanism to provision stake to a data + * service, where the data service is the verifier. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param _tokens The amount of tokens that will be locked and slashable + * @param _maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param _thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + */ + function provision( + address _serviceProvider, + address _verifier, + uint256 _tokens, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { + if (getIdleStake(_serviceProvider) < _tokens) { + revert HorizonStakingInsufficientCapacity(); + } + + _createProvision(_serviceProvider, _tokens, _verifier, _maxVerifierCut, _thawingPeriod); + } + + /** + * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period + * and will be slashable by the verifier. This is the main mechanism to provision stake to a data + * service, where the data service is the verifier. Only authorized verifiers can be used. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param _tokens The amount of tokens that will be locked and slashable + * @param _maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param _thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + */ + function provisionLocked( + address _serviceProvider, + address _verifier, + uint256 _tokens, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { + if (getIdleStake(_serviceProvider) < _tokens) { + revert HorizonStakingInsufficientCapacity(); + } + if (!allowedLockedVerifiers[_verifier]) { + revert HorizonStakingInvalidVerifier(_verifier); + } + _createProvision(_serviceProvider, _tokens, _verifier, _maxVerifierCut, _thawingPeriod); + } + + /** + * @notice Add more tokens to an existing provision. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned + * @param _tokens The amount of tokens to add to the provision + */ + function addToProvision( + address _serviceProvider, + address _verifier, + uint256 _tokens + ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { + _addToProvision(_serviceProvider, _verifier, _tokens); + } + + /** + * @notice Start thawing tokens to remove them from a provision. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned + * @param _tokens The amount of tokens to thaw + */ + function thaw( + address _serviceProvider, + address _verifier, + uint256 _tokens + ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) returns (bytes32) { + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + Provision storage prov = provisions[_serviceProvider][_verifier]; + ServiceProviderInternal storage serviceProvider = serviceProviders[_serviceProvider]; + bytes32 thawRequestId = keccak256( + abi.encodePacked(_serviceProvider, _verifier, serviceProvider.nextThawRequestNonce) + ); + serviceProvider.nextThawRequestNonce += 1; + ThawRequest storage thawRequest = thawRequests[thawRequestId]; + + require(getProviderTokensAvailable(_serviceProvider, _verifier) >= _tokens, "insufficient tokens available"); + prov.tokensThawing = prov.tokensThawing + _tokens; + + if (prov.sharesThawing == 0) { + thawRequest.shares = _tokens; + } else { + thawRequest.shares = (prov.sharesThawing * _tokens) / prov.tokensThawing; + } + + thawRequest.thawingUntil = uint64(block.timestamp + uint256(prov.thawingPeriod)); + prov.sharesThawing = prov.sharesThawing + thawRequest.shares; + + if (prov.nThawRequests >= MAX_THAW_REQUESTS) { + revert HorizonStakingTooManyThawRequests(); + } + if (prov.nThawRequests == 0) { + prov.firstThawRequestId = thawRequestId; + } else { + thawRequests[prov.lastThawRequestId].next = thawRequestId; + } + prov.lastThawRequestId = thawRequestId; + prov.nThawRequests += 1; + + emit ProvisionThawInitiated(_serviceProvider, _verifier, _tokens, thawRequest.thawingUntil, thawRequestId); + + return thawRequestId; + } + + /** + * @notice Get the amount of service provider's tokens in a provision that have finished thawing + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned + */ + function getThawedTokens(address _serviceProvider, address _verifier) external view returns (uint256) { + Provision storage prov = provisions[_serviceProvider][_verifier]; + if (prov.nThawRequests == 0) { + return 0; + } + bytes32 thawRequestId = prov.firstThawRequestId; + uint256 tokens = 0; + while (thawRequestId != bytes32(0)) { + ThawRequest storage thawRequest = thawRequests[thawRequestId]; + if (thawRequest.thawingUntil <= block.timestamp) { + tokens += (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; + } else { + break; + } + thawRequestId = thawRequest.next; + } + return tokens; + } + + // moves thawed stake from a provision back into the provider's available stake + function deprovision( + address _serviceProvider, + address _verifier, + uint256 _tokens + ) external override notPartialPaused { + require(isAuthorized(msg.sender, _serviceProvider, _verifier), "!auth"); + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + _fulfillThawRequests(_serviceProvider, _verifier, _tokens); + } + + /** + * @notice Move already thawed stake from one provision into another provision + * This function can be called by the service provider or by an operator authorized by the provider + * for the two corresponding verifiers. + * The provider must have previously provisioned tokens to the new verifier. + * @param _serviceProvider The service provider address + * @param _oldVerifier The verifier address for which the tokens are currently provisioned + * @param _newVerifier The verifier address for which the tokens will be provisioned + * @param _tokens The amount of tokens to move + */ + function reprovision( + address _serviceProvider, + address _oldVerifier, + address _newVerifier, + uint256 _tokens + ) + external + override + notPartialPaused + onlyAuthorized(_serviceProvider, _oldVerifier) + onlyAuthorized(_serviceProvider, _newVerifier) + { + _fulfillThawRequests(_serviceProvider, _oldVerifier, _tokens); + _addToProvision(_serviceProvider, _newVerifier, _tokens); + } + + /** + * @notice Move idle stake back to the owner's account. + * If tokens were thawing they must be deprovisioned first. + * Stake is removed from the protocol. + * @param _tokens Amount of tokens to unstake + */ + function unstake(uint256 _tokens) external override notPaused { + address serviceProvider = msg.sender; + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + if (getIdleStake(serviceProvider) < _tokens) { + revert HorizonStakingInsufficientCapacity(); + } + + ServiceProviderInternal storage sp = serviceProviders[serviceProvider]; + uint256 stakedTokens = sp.tokensStaked; + // Check that the indexer's stake minus the tokens to unstake is sufficient + // to cover existing allocations + // TODO this is only needed until legacy allocations are closed, + // so we should remove it after the transition period + if ((stakedTokens - _tokens) < sp.__DEPRECATED_tokensAllocated) { + revert HorizonStakingInsufficientCapacityForLegacyAllocations(); + } + + // This is also only during the transition period: we need + // to ensure tokens stay locked after closing legacy allocations. + // After sufficient time (56 days?) we should remove the closeAllocation function + // and set the thawing period to 0. + uint256 lockingPeriod = __DEPRECATED_thawingPeriod; + if (lockingPeriod == 0) { + sp.tokensStaked = stakedTokens - _tokens; + TokenUtils.pushTokens(_graphToken(), serviceProvider, _tokens); + emit StakeWithdrawn(serviceProvider, _tokens); + } else { + // Before locking more tokens, withdraw any unlocked ones if possible + if (sp.__DEPRECATED_tokensLockedUntil != 0 && block.number >= sp.__DEPRECATED_tokensLockedUntil) { + _withdraw(serviceProvider); + } + // TODO remove after the transition period + // Take into account period averaging for multiple unstake requests + if (sp.__DEPRECATED_tokensLocked > 0) { + lockingPeriod = MathUtils.weightedAverageRoundingUp( + MathUtils.diffOrZero(sp.__DEPRECATED_tokensLockedUntil, block.number), // Remaining thawing period + sp.__DEPRECATED_tokensLocked, // Weighted by remaining unstaked tokens + lockingPeriod, // Thawing period + _tokens // Weighted by new tokens to unstake + ); + } + + // Update balances + sp.__DEPRECATED_tokensLocked = sp.__DEPRECATED_tokensLocked + _tokens; + sp.__DEPRECATED_tokensLockedUntil = block.number + lockingPeriod; + emit StakeLocked(serviceProvider, sp.__DEPRECATED_tokensLocked, sp.__DEPRECATED_tokensLockedUntil); + } + } + + /** + * @notice Slash a service provider. This can only be called by a verifier to which + * the provider has provisioned stake, and up to the amount of tokens they have provisioned. + * @dev If delegation slashing is disabled, and the amount of tokens is more than the + * provider's provisioned self-stake, the delegation slashing is skipped without reverting. + * @param _serviceProvider The service provider to slash + * @param _tokens The amount of tokens to slash + * @param _verifierCutAmount The amount of tokens to transfer instead of burning + * @param _verifierCutDestination The address to transfer the verifier cut to + */ + function slash( + address _serviceProvider, + uint256 _tokens, + uint256 _verifierCutAmount, + address _verifierCutDestination + ) external override notPartialPaused { + address verifier = msg.sender; + Provision storage prov = provisions[_serviceProvider][verifier]; + if (prov.tokens < _tokens) { + revert HorizonStakingInsufficientTokens(_tokens, prov.tokens); + } + + uint256 tokensToSlash = _tokens; + uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); + if (providerTokensSlashed > 0) { + require((prov.tokens * prov.maxVerifierCut) / MAX_PPM >= _verifierCutAmount, "verifier cut too high"); + if (_verifierCutAmount > 0) { + TokenUtils.pushTokens(_graphToken(), _verifierCutDestination, _verifierCutAmount); + emit VerifierCutSent(_serviceProvider, verifier, _verifierCutDestination, _verifierCutAmount); + } + TokenUtils.burnTokens(_graphToken(), providerTokensSlashed - _verifierCutAmount); + uint256 provisionFractionSlashed = (providerTokensSlashed * FIXED_POINT_PRECISION) / prov.tokens; + // TODO check for rounding issues + prov.tokensThawing = + (prov.tokensThawing * (FIXED_POINT_PRECISION - provisionFractionSlashed)) / + (FIXED_POINT_PRECISION); + prov.tokens = prov.tokens - providerTokensSlashed; + serviceProviders[_serviceProvider].tokensProvisioned = + serviceProviders[_serviceProvider].tokensProvisioned - + providerTokensSlashed; + serviceProviders[_serviceProvider].tokensStaked = + serviceProviders[_serviceProvider].tokensStaked - + providerTokensSlashed; + emit ProvisionSlashed(_serviceProvider, verifier, providerTokensSlashed); + } + + tokensToSlash = tokensToSlash - providerTokensSlashed; + if (tokensToSlash > 0) { + DelegationPoolInternal storage pool; + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = legacyDelegationPools[_serviceProvider]; + } else { + pool = delegationPools[_serviceProvider][verifier]; + } + if (delegationSlashingEnabled) { + require(pool.tokens >= tokensToSlash, "insufficient delegated tokens"); + TokenUtils.burnTokens(_graphToken(), tokensToSlash); + uint256 delegationFractionSlashed = (tokensToSlash * FIXED_POINT_PRECISION) / pool.tokens; + pool.tokens = pool.tokens - tokensToSlash; + pool.tokensThawing = + (pool.tokensThawing * (FIXED_POINT_PRECISION - delegationFractionSlashed)) / + FIXED_POINT_PRECISION; + emit DelegationSlashed(_serviceProvider, verifier, tokensToSlash); + } else { + emit DelegationSlashingSkipped(_serviceProvider, verifier, tokensToSlash); + } + } + } + + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param _operator The address to check for auth + * @param _serviceProvider The service provider on behalf of whom they're claiming to act + * @param _verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized( + address _operator, + address _serviceProvider, + address _verifier + ) public view override returns (bool) { + if (_operator == _serviceProvider) { + return true; + } + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return legacyOperatorAuth[_serviceProvider][_operator]; + } else { + return operatorAuth[_serviceProvider][_verifier][_operator]; + } + } + + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address serviceProvider) public view override returns (uint256 tokens) { + return + serviceProviders[serviceProvider].tokensStaked - + serviceProviders[serviceProvider].tokensProvisioned - + serviceProviders[serviceProvider].__DEPRECATED_tokensLocked; + } + + // provisioned tokens from the service provider that are not being thawed + // `Provision.tokens - Provision.tokensThawing` + function getProviderTokensAvailable( + address _serviceProvider, + address _verifier + ) public view override returns (uint256) { + return provisions[_serviceProvider][_verifier].tokens - provisions[_serviceProvider][_verifier].tokensThawing; + } + + function setAllowedLockedVerifier(address _verifier, bool _allowed) external onlyGovernor { + allowedLockedVerifiers[_verifier] = _allowed; + emit AllowedLockedVerifierSet(_verifier, _allowed); + } + + /** + * @notice Withdraw indexer tokens once the thawing period has passed. + * @dev This is only needed during the transition period while we still have + * a global lock. After that, unstake() will also withdraw. + */ + function withdraw() external override notPaused { + _withdraw(msg.sender); + } + + function delegate( + address _serviceProvider, + address _verifier, + uint256 _tokens, + uint256 _minSharesOut + ) public override notPartialPaused { + // Transfer tokens to stake from caller to this contract + TokenUtils.pullTokens(_graphToken(), msg.sender, _tokens); + _delegate(_serviceProvider, _verifier, _tokens, _minSharesOut); + } + + // For backwards compatibility, delegates to the subgraph data service + // (Note this one doesn't have splippage/rounding protection!) + function delegate(address _serviceProvider, uint256 _tokens) external { + delegate(_serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, _tokens, 0); + } + + // For backwards compatibility, undelegates from the subgraph data service + function undelegate(address _serviceProvider, uint256 _shares) external { + undelegate(_serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, _shares); + } + + // For backwards compatibility, withdraws delegated tokens from the subgraph data service + function withdrawDelegated(address _serviceProvider, address _newServiceProvider) external { + withdrawDelegated(_serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, _newServiceProvider, 0); + } + + function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) internal { + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + // TODO: remove this after L2 transfer tool for delegation is removed + if (_tokens < MIN_DELEGATION) { + revert HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens); + } + if (provisions[_serviceProvider][_verifier].tokens == 0) { + revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); + } + + DelegationPoolInternal storage pool; + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = legacyDelegationPools[_serviceProvider]; + } else { + pool = delegationPools[_serviceProvider][_verifier]; + } + Delegation storage delegation = pool.delegators[msg.sender]; + + // Calculate shares to issue + uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); + if (shares == 0 || shares < _minSharesOut) { + revert HorizonStakingSlippageProtection(_minSharesOut, shares); + } + + pool.tokens = pool.tokens + _tokens; + pool.shares = pool.shares + shares; + + delegation.shares = delegation.shares + shares; + + emit TokensDelegated(_serviceProvider, _verifier, msg.sender, _tokens); + } + + // undelegate tokens from a service provider + // the shares are burned and replaced with shares in the thawing pool + function undelegate(address _serviceProvider, address _verifier, uint256 _shares) public override notPartialPaused { + require(_shares > 0, "!shares"); + DelegationPoolInternal storage pool; + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = legacyDelegationPools[_serviceProvider]; + } else { + pool = delegationPools[_serviceProvider][_verifier]; + } + Delegation storage delegation = pool.delegators[msg.sender]; + require(delegation.shares >= _shares, "!shares-avail"); + + uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; + + uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); + pool.tokensThawing = pool.tokensThawing + tokens; + + pool.shares = pool.shares - _shares; + pool.sharesThawing = pool.sharesThawing + thawingShares; + + delegation.shares = delegation.shares - _shares; + // TODO: remove this when L2 transfer tools are removed + if (delegation.shares != 0) { + uint256 remainingTokens = (delegation.shares * (pool.tokens - pool.tokensThawing)) / pool.shares; + require(remainingTokens >= MIN_DELEGATION, "!minimum-delegation"); + } + bytes32 thawRequestId = keccak256( + abi.encodePacked(_serviceProvider, _verifier, msg.sender, delegation.nextThawRequestNonce) + ); + delegation.nextThawRequestNonce += 1; + ThawRequest storage thawRequest = thawRequests[thawRequestId]; + thawRequest.shares = thawingShares; + thawRequest.thawingUntil = uint64( + block.timestamp + uint256(provisions[_serviceProvider][_verifier].thawingPeriod) + ); + require(delegation.nThawRequests < MAX_THAW_REQUESTS, "max thaw requests"); + if (delegation.nThawRequests == 0) { + delegation.firstThawRequestId = thawRequestId; + } else { + thawRequests[delegation.lastThawRequestId].next = thawRequestId; + } + delegation.lastThawRequestId = thawRequestId; + unchecked { + delegation.nThawRequests += 1; + } + emit TokensUndelegated(_serviceProvider, _verifier, msg.sender, tokens); + } + + /** + * @notice Add tokens to a delegation pool (without getting shares). + * Used by data services to pay delegation fees/rewards. + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned + * @param _tokens The amount of tokens to add to the delegation pool + */ + function addToDelegationPool( + address _serviceProvider, + address _verifier, + uint256 _tokens + ) external override notPartialPaused { + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + DelegationPoolInternal storage pool; + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = legacyDelegationPools[_serviceProvider]; + } else { + pool = delegationPools[_serviceProvider][_verifier]; + } + pool.tokens = pool.tokens + _tokens; + emit TokensAddedToDelegationPool(_serviceProvider, _verifier, _tokens); + } + + function withdrawDelegated( + address _serviceProvider, + address _verifier, + address _newServiceProvider, + uint256 _minSharesForNewProvider + ) public override notPartialPaused { + DelegationPoolInternal storage pool; + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = legacyDelegationPools[_serviceProvider]; + } else { + pool = delegationPools[_serviceProvider][_verifier]; + } + Delegation storage delegation = pool.delegators[msg.sender]; + uint256 thawedTokens = 0; + + uint256 sharesThawing = pool.sharesThawing; + uint256 tokensThawing = pool.tokensThawing; + require(delegation.nThawRequests > 0, "no thaw requests"); + bytes32 thawRequestId = delegation.firstThawRequestId; + while (thawRequestId != bytes32(0)) { + ThawRequest storage thawRequest = thawRequests[thawRequestId]; + if (thawRequest.thawingUntil <= block.timestamp) { + uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; + tokensThawing = tokensThawing - tokens; + sharesThawing = sharesThawing - thawRequest.shares; + thawedTokens = thawedTokens + tokens; + delete thawRequests[thawRequestId]; + delegation.firstThawRequestId = thawRequest.next; + delegation.nThawRequests -= 1; + if (delegation.nThawRequests == 0) { + delegation.lastThawRequestId = bytes32(0); + } + } else { + break; + } + thawRequestId = thawRequest.next; + } + + pool.tokens = pool.tokens - thawedTokens; + pool.sharesThawing = sharesThawing; + pool.tokensThawing = tokensThawing; + + if (_newServiceProvider != address(0)) { + _delegate(_newServiceProvider, _verifier, thawedTokens, _minSharesForNewProvider); + } else { + TokenUtils.pushTokens(_graphToken(), msg.sender, thawedTokens); + } + emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, thawedTokens); + } + + function setDelegationSlashingEnabled(bool _enabled) external override onlyGovernor { + delegationSlashingEnabled = _enabled; + emit DelegationSlashingEnabled(_enabled); + } + + // To be called at the end of the transition period, to set the deprecated thawing period to 0 + function clearThawingPeriod() external onlyGovernor { + __DEPRECATED_thawingPeriod = 0; + emit ParameterUpdated("thawingPeriod"); + } + + function setMaxThawingPeriod(uint64 _maxThawingPeriod) external override onlyGovernor { + maxThawingPeriod = _maxThawingPeriod; + emit ParameterUpdated("maxThawingPeriod"); + } + + /** + * @dev Withdraw indexer tokens once the thawing period has passed. + * @param _indexer Address of indexer to withdraw funds from + */ + function _withdraw(address _indexer) private { + // Get tokens available for withdraw and update balance + ServiceProviderInternal storage sp = serviceProviders[_indexer]; + uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; + require(tokensToWithdraw > 0, "!tokens"); + require(block.number >= sp.__DEPRECATED_tokensLockedUntil, "locked"); + + // Reset locked tokens + sp.__DEPRECATED_tokensLocked = 0; + sp.__DEPRECATED_tokensLockedUntil = 0; + + sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; + + // Return tokens to the indexer + TokenUtils.pushTokens(_graphToken(), _indexer, tokensToWithdraw); + + emit StakeWithdrawn(_indexer, tokensToWithdraw); + } + + /** + * @dev Creates a provision + */ + function _createProvision( + address _serviceProvider, + uint256 _tokens, + address _verifier, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) internal { + require(_tokens >= MIN_PROVISION_SIZE, "!tokens"); + require(_maxVerifierCut <= MAX_MAX_VERIFIER_CUT, "maxVerifierCut too high"); + require(_thawingPeriod <= maxThawingPeriod, "thawingPeriod too high"); + provisions[_serviceProvider][_verifier] = Provision({ + tokens: _tokens, + tokensThawing: 0, + sharesThawing: 0, + maxVerifierCut: _maxVerifierCut, + thawingPeriod: _thawingPeriod, + createdAt: uint64(block.timestamp), + firstThawRequestId: bytes32(0), + lastThawRequestId: bytes32(0), + nThawRequests: 0, + maxVerifierCutPending: _maxVerifierCut, + thawingPeriodPending: _thawingPeriod + }); + + ServiceProviderInternal storage sp = serviceProviders[_serviceProvider]; + sp.tokensProvisioned = sp.tokensProvisioned + _tokens; + + emit ProvisionCreated(_serviceProvider, _verifier, _tokens, _maxVerifierCut, _thawingPeriod); + } + + function _fulfillThawRequests(address _serviceProvider, address _verifier, uint256 _tokens) internal { + Provision storage prov = provisions[_serviceProvider][_verifier]; + uint256 tokensRemaining = _tokens; + uint256 sharesThawing = prov.sharesThawing; + uint256 tokensThawing = prov.tokensThawing; + while (tokensRemaining > 0) { + require(prov.nThawRequests > 0, "not enough thawed tokens"); + bytes32 thawRequestId = prov.firstThawRequestId; + ThawRequest storage thawRequest = thawRequests[thawRequestId]; + require(thawRequest.thawingUntil <= block.timestamp, "thawing period not over"); + uint256 thawRequestTokens = (thawRequest.shares * tokensThawing) / sharesThawing; + if (thawRequestTokens <= tokensRemaining) { + tokensRemaining = tokensRemaining - thawRequestTokens; + delete thawRequests[thawRequestId]; + prov.firstThawRequestId = thawRequest.next; + prov.nThawRequests -= 1; + tokensThawing = tokensThawing - thawRequestTokens; + sharesThawing = sharesThawing - thawRequest.shares; + if (prov.nThawRequests == 0) { + prov.lastThawRequestId = bytes32(0); + } + } else { + // TODO check for potential rounding issues + uint256 sharesRemoved = (tokensRemaining * prov.sharesThawing) / prov.tokensThawing; + thawRequest.shares = thawRequest.shares - sharesRemoved; + tokensThawing = tokensThawing - tokensRemaining; + sharesThawing = sharesThawing - sharesRemoved; + } + emit ProvisionThawFulfilled( + _serviceProvider, + _verifier, + MathUtils.min(thawRequestTokens, tokensRemaining), + thawRequestId + ); + } + prov.sharesThawing = sharesThawing; + prov.tokensThawing = tokensThawing; + prov.tokens = prov.tokens - _tokens; + serviceProviders[_serviceProvider].tokensProvisioned -= _tokens; + } + + function _addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) internal { + Provision storage prov = provisions[_serviceProvider][_verifier]; + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + if (prov.createdAt == 0) { + revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); + } + if (getIdleStake(_serviceProvider) < _tokens) { + revert HorizonStakingInsufficientCapacity(); + } + + prov.tokens = prov.tokens + _tokens; + serviceProviders[_serviceProvider].tokensProvisioned = + serviceProviders[_serviceProvider].tokensProvisioned + + _tokens; + emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); + } + + /** + * @dev Stake tokens on the service provider. + * TODO: Move to HorizonStaking after the transition period + * @param _serviceProvider Address of staking party + * @param _tokens Amount of tokens to stake + */ + function _stake(address _serviceProvider, uint256 _tokens) internal { + // Deposit tokens into the indexer stake + serviceProviders[_serviceProvider].tokensStaked = serviceProviders[_serviceProvider].tokensStaked + _tokens; + + emit StakeDeposited(_serviceProvider, _tokens); + } + + function _graphToken() internal view returns (IGraphToken) { + return IGraphToken(GRAPH_TOKEN); + } +} diff --git a/packages/horizon/contracts/HorizonStakingExtension.sol b/packages/horizon/contracts/HorizonStakingExtension.sol new file mode 100644 index 000000000..1ec8b2c45 --- /dev/null +++ b/packages/horizon/contracts/HorizonStakingExtension.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { StakingBackwardsCompatibility } from "./StakingBackwardsCompatibility.sol"; +import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; +import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; +import { IHorizonStakingExtension } from "./IHorizonStakingExtension.sol"; +import { MathUtils } from "./utils/MathUtils.sol"; + +/** + * @title L2Staking contract + * @dev 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. + */ +contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStakingExtension, IL2StakingBase { + /// @dev Minimum amount of tokens that can be delegated + uint256 private constant MINIMUM_DELEGATION = 1e18; + + /** + * @dev Checks that the sender is the L2GraphTokenGateway as configured on the Controller. + */ + modifier onlyL2Gateway() { + require(msg.sender == GRAPH_TOKEN_GATEWAY, "ONLY_GATEWAY"); + _; + } + + constructor( + address _controller, + address _subgraphDataServiceAddress, + address _exponentialRebates + ) StakingBackwardsCompatibility(_controller, _subgraphDataServiceAddress, _exponentialRebates) {} + + /** + * @notice Receive ETH into the Staking contract: this will always revert + * @dev This function is only here to prevent ETH from being sent to the contract + */ + receive() external payable { + revert("RECEIVE_ETH_NOT_ALLOWED"); + } + + // total staked tokens to the provider + // `ServiceProvider.tokensStaked + function getStake(address serviceProvider) external view override returns (uint256) { + return serviceProviders[serviceProvider].tokensStaked; + } + + // provisioned tokens from delegators that are not being thawed + // `Provision.delegatedTokens - Provision.delegatedTokensThawing` + function getDelegatedTokensAvailable( + address _serviceProvider, + address _verifier + ) public view override returns (uint256) { + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return + legacyDelegationPools[_serviceProvider].tokens - + (legacyDelegationPools[_serviceProvider].tokensThawing); + } + return + delegationPools[_serviceProvider][_verifier].tokens - + (delegationPools[_serviceProvider][_verifier].tokensThawing); + } + + // provisioned tokens that are not being thawed (including provider tokens and delegation) + function getTokensAvailable( + address _serviceProvider, + address _verifier, + uint32 _delegationRatio + ) external view override returns (uint256) { + uint256 providerTokens = provisions[_serviceProvider][_verifier].tokens; + uint256 tokensDelegatedMax = providerTokens * (uint256(_delegationRatio)); + uint256 tokensDelegatedCapacity = MathUtils.min( + getDelegatedTokensAvailable(_serviceProvider, _verifier), + tokensDelegatedMax + ); + return providerTokens - provisions[_serviceProvider][_verifier].tokensThawing + tokensDelegatedCapacity; + } + + function getServiceProvider(address serviceProvider) external view override returns (ServiceProvider memory) { + ServiceProvider memory sp; + ServiceProviderInternal storage spInternal = serviceProviders[serviceProvider]; + sp.tokensStaked = spInternal.tokensStaked; + sp.tokensProvisioned = spInternal.tokensProvisioned; + sp.nextThawRequestNonce = spInternal.nextThawRequestNonce; + return sp; + } + + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @param _operator Address to authorize or unauthorize + * @param _verifier The verifier / data service on which they'll be allowed to operate + * @param _allowed Whether the operator is authorized or not + */ + function setOperator(address _operator, address _verifier, bool _allowed) external override { + require(_operator != msg.sender, "operator == sender"); + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + legacyOperatorAuth[msg.sender][_operator] = _allowed; + } else { + operatorAuth[msg.sender][_verifier][_operator] = _allowed; + } + emit OperatorSet(msg.sender, _operator, _verifier, _allowed); + } + + // for vesting contracts + function setOperatorLocked(address _operator, address _verifier, bool _allowed) external override { + require(_operator != msg.sender, "operator == sender"); + require(allowedLockedVerifiers[_verifier], "VERIFIER_NOT_ALLOWED"); + operatorAuth[msg.sender][_verifier][_operator] = _allowed; + emit OperatorSet(msg.sender, _operator, _verifier, _allowed); + } + + function getMaxThawingPeriod() external view override returns (uint64) { + return maxThawingPeriod; + } + + /** + * @notice Receive tokens with a callhook from the bridge. + * @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. + * @param _from Token sender in L1 + * @param _amount Amount of tokens that were transferred + * @param _data ABI-encoded callhook data which must include a uint8 code and either a ReceiveIndexerStakeData or ReceiveDelegationData struct. + */ + function onTokenTransfer( + address _from, + uint256 _amount, + bytes calldata _data + ) external override notPartialPaused onlyL2Gateway { + require(_from == counterpartStakingAddress, "ONLY_L1_STAKING_THROUGH_BRIDGE"); + (uint8 code, bytes memory functionData) = abi.decode(_data, (uint8, bytes)); + + if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_INDEXER_STAKE_CODE)) { + IL2StakingTypes.ReceiveIndexerStakeData memory indexerData = abi.decode( + functionData, + (IL2StakingTypes.ReceiveIndexerStakeData) + ); + _receiveIndexerStake(_amount, indexerData); + } else if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE)) { + IL2StakingTypes.ReceiveDelegationData memory delegationData = abi.decode( + functionData, + (IL2StakingTypes.ReceiveDelegationData) + ); + _receiveDelegation(_amount, delegationData); + } else { + revert("INVALID_CODE"); + } + } + + function getDelegationPool( + address _serviceProvider, + address _verifier + ) external view override returns (DelegationPool memory) { + DelegationPool memory pool; + DelegationPoolInternal storage poolInternal; + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + poolInternal = legacyDelegationPools[_serviceProvider]; + } else { + poolInternal = delegationPools[_serviceProvider][_verifier]; + } + pool.tokens = poolInternal.tokens; + pool.shares = poolInternal.shares; + pool.tokensThawing = poolInternal.tokensThawing; + pool.sharesThawing = poolInternal.sharesThawing; + return pool; + } + + function getDelegation( + address _delegator, + address _serviceProvider, + address _verifier + ) external view override returns (Delegation memory) { + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return legacyDelegationPools[_serviceProvider].delegators[_delegator]; + } else { + return delegationPools[_serviceProvider][_verifier].delegators[_delegator]; + } + } + + function getThawRequest(bytes32 _thawRequestId) external view returns (ThawRequest memory) { + return thawRequests[_thawRequestId]; + } + + function getProvision( + address _serviceProvider, + address _verifier + ) external view override returns (Provision memory) { + return provisions[_serviceProvider][_verifier]; + } + + function setDelegationFeeCut( + address _serviceProvider, + address _verifier, + uint256 _feeType, + uint256 _feeCut + ) external override { + delegationFeeCut[_serviceProvider][_verifier][_feeType] = _feeCut; + emit DelegationFeeCutSet(_serviceProvider, _verifier, _feeType, _feeCut); + } + + function getDelegationFeeCut( + address _serviceProvider, + address _verifier, + uint256 _feeType + ) external view override returns (uint256) { + return delegationFeeCut[_serviceProvider][_verifier][_feeType]; + } + + /** + * @dev 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 + * @param _indexerData struct containing the indexer's address + */ + function _receiveIndexerStake( + uint256 _amount, + IL2StakingTypes.ReceiveIndexerStakeData memory _indexerData + ) internal { + address _indexer = _indexerData.indexer; + // Deposit tokens into the indexer stake + _stake(_indexer, _amount); + } + + /** + * @dev 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. + * @param _amount Amount of tokens that were transferred + * @param _delegationData struct containing the delegator's address and the indexer's address + */ + function _receiveDelegation( + uint256 _amount, + IL2StakingTypes.ReceiveDelegationData memory _delegationData + ) internal { + // Get the delegation pool of the indexer + DelegationPoolInternal storage pool = legacyDelegationPools[_delegationData.indexer]; + Delegation storage delegation = pool.delegators[_delegationData.delegator]; + + // Calculate shares to issue (without applying any delegation tax) + uint256 shares = (pool.tokens == 0) ? _amount : ((_amount * pool.shares) / pool.tokens); + + if (shares == 0 || _amount < MINIMUM_DELEGATION) { + // If no shares would be issued (probably a rounding issue or attack), + // or if the amount is under the minimum delegation (which could be part of a rounding attack), + // return the tokens to the delegator + _graphToken().transfer(_delegationData.delegator, _amount); + emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _amount); + } else { + // Update the delegation pool + pool.tokens = pool.tokens + _amount; + pool.shares = pool.shares + shares; + + // Update the individual delegation + delegation.shares = delegation.shares + shares; + + emit StakeDelegated(_delegationData.indexer, _delegationData.delegator, _amount, shares); + } + } +} diff --git a/packages/horizon/contracts/HorizonStakingStorage.sol b/packages/horizon/contracts/HorizonStakingStorage.sol new file mode 100644 index 000000000..6506429a7 --- /dev/null +++ b/packages/horizon/contracts/HorizonStakingStorage.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { Managed } from "./Managed.sol"; +import { IStakingBackwardsCompatibility } from "./IStakingBackwardsCompatibility.sol"; +import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; + +/** + * @title HorizonStakingV1Storage + * @notice This contract holds all the storage variables for the Staking contract, version 1 + */ +// solhint-disable-next-line max-states-count +abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { + // -- Staking -- + + /// @dev Minimum amount of tokens an indexer needs to stake. + /// Deprecated, now enforced by each data service (verifier) + uint256 internal __DEPRECATED_minimumIndexerStake; + + /// @dev Time in blocks to unstake + /// Deprecated, now enforced by each data service (verifier) + uint32 internal __DEPRECATED_thawingPeriod; // in blocks + + /// @dev Percentage of fees going to curators + /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) + /// Deprecated, now enforced by each data service (verifier) + uint32 internal __DEPRECATED_curationPercentage; + + /// @dev Percentage of fees burned as protocol fee + /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) + /// Deprecated, now enforced by each data service (verifier) + uint32 internal __DEPRECATED_protocolPercentage; + + /// @dev Period for allocation to be finalized + uint32 private __DEPRECATED_channelDisputeEpochs; // solhint-disable-line var-name-mixedcase + + /// @dev Maximum allocation time. Deprecated, allocations now live on the subgraph service contract. + uint32 internal __DEPRECATED_maxAllocationEpochs; + + /// @dev Rebate alpha numerator + /// Originally used for Cobb-Douglas rebates, now used for exponential rebates + /// Deprecated, now applied on the SubgraphService + uint32 internal __DEPRECATED_alphaNumerator; + + /// @dev Rebate alpha denominator + /// Originally used for Cobb-Douglas rebates, now used for exponential rebates + /// Deprecated, now applied on the SubgraphService + uint32 internal __DEPRECATED_alphaDenominator; + + /// @dev Service provider stakes : serviceProviderAddress => ServiceProvider + mapping(address => ServiceProviderInternal) internal serviceProviders; + + /// @dev Allocations : allocationID => Allocation + /// Deprecated, now applied on the SubgraphService + mapping(address => IStakingBackwardsCompatibility.Allocation) internal __DEPRECATED_allocations; + + /// @dev Subgraph Allocations: subgraphDeploymentID => tokens + /// Deprecated, now applied on the SubgraphService + mapping(bytes32 => uint256) internal __DEPRECATED_subgraphAllocations; + + /// @dev Rebate pools : epoch => Pool + /// Deprecated. + mapping(uint256 => uint256) private __DEPRECATED_rebates; // solhint-disable-line var-name-mixedcase + + // -- Slashing -- + + /// @dev List of addresses allowed to slash stakes + /// Deprecated, now each verifier can slash the corresponding provision. + mapping(address => bool) internal __DEPRECATED_slashers; + + // -- Delegation -- + + /// @dev Delegation capacity multiplier defined by the delegation ratio + /// Deprecated, now applied by each data service as needed. + uint32 internal __DEPRECATED_delegationRatio; + + /// @dev Time in blocks an indexer needs to wait to change delegation parameters (deprecated) + uint32 internal __DEPRECATED_delegationParametersCooldown; // solhint-disable-line var-name-mixedcase + + /// @dev Time in epochs a delegator needs to wait to withdraw delegated stake + /// Deprecated, now only enforced during a transition period + uint32 internal __DEPRECATED_delegationUnbondingPeriod; // in epochs + + /// @dev Percentage of tokens to tax a delegation deposit + /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) + /// Deprecated, no tax is applied now. + uint32 internal __DEPRECATED_delegationTaxPercentage; + + /// @dev Delegation pools : serviceProvider => DelegationPoolInternal + /// These are for the subgraph data service. + mapping(address => DelegationPoolInternal) internal legacyDelegationPools; + + // -- Operators -- + + /// @dev Legacy operator auth : indexer => operator => is authorized + mapping(address => mapping(address => bool)) internal legacyOperatorAuth; + + // -- Asset Holders -- + + /// @dev DEPRECATED: Allowed AssetHolders: assetHolder => is allowed + mapping(address => bool) private __DEPRECATED_assetHolders; // solhint-disable-line var-name-mixedcase + + /// @dev Destination of accrued rewards : beneficiary => rewards destination + /// Deprecated, defined by each data service as needed + mapping(address => address) internal __DEPRECATED_rewardsDestination; + + /// @dev Address of the counterpart Staking contract on L1/L2 + address internal counterpartStakingAddress; + /// @dev Address of the StakingExtension implementation + address internal __DEPRECATED_extensionImpl; + + // Additional rebate parameters for exponential rebates + uint32 internal __DEPRECATED_lambdaNumerator; + uint32 internal __DEPRECATED_lambdaDenominator; + + /// Maximum thawing period, in seconds, for a provision + uint64 internal maxThawingPeriod; + + /// @dev Provisions from each service provider for each data service + /// ServiceProvider => Verifier => Provision + mapping(address => mapping(address => Provision)) internal provisions; + + /// @dev Delegation fee cuts for each service provider on each provision, by fee type: + /// ServiceProvider => Verifier => Fee Type => Fee Cut. + /// This is the effective delegator fee cuts for each (data-service-defined) fee type (e.g. indexing fees, query fees). + /// This is in PPM and is the cut taken by the indexer from the fees that correspond to delegators. + /// (based on stake vs delegated stake proportion). + /// The cuts are applied in GraphPayments so apply to all data services that use it. + mapping(address => mapping(address => mapping(uint256 => uint256))) public delegationFeeCut; + + mapping(bytes32 => ThawRequest) internal thawRequests; + + // indexer => verifier => operator => authorized + mapping(address => mapping(address => mapping(address => bool))) internal operatorAuth; + + // governance enables or disables delegation slashing with this flag + bool public delegationSlashingEnabled; + + // delegation pools for each service provider and verifier + mapping(address => mapping(address => DelegationPoolInternal)) internal delegationPools; + + // allowed verifiers for locked provisions (i.e. from GraphTokenLockWallets) + mapping(address => bool) internal allowedLockedVerifiers; +} diff --git a/packages/horizon/contracts/IGraphToken.sol b/packages/horizon/contracts/IGraphToken.sol new file mode 100644 index 000000000..fd0b0a553 --- /dev/null +++ b/packages/horizon/contracts/IGraphToken.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IGraphToken is IERC20 { + // -- Mint and Burn -- + + function burn(uint256 amount) external; + + function burnFrom(address _from, uint256 amount) external; + + function mint(address _to, uint256 _amount) external; + + // -- Mint Admin -- + + function addMinter(address _account) external; + + function removeMinter(address _account) external; + + function renounceMinter() external; + + function isMinter(address _account) external view returns (bool); + + // -- Permit -- + + function permit( + address _owner, + address _spender, + uint256 _value, + uint256 _deadline, + uint8 _v, + bytes32 _r, + bytes32 _s + ) external; + + // -- Allowance -- + + function increaseAllowance(address spender, uint256 addedValue) external returns (bool); + + function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); +} diff --git a/packages/horizon/contracts/IHorizonStaking.sol b/packages/horizon/contracts/IHorizonStaking.sol new file mode 100644 index 000000000..2c9dab033 --- /dev/null +++ b/packages/horizon/contracts/IHorizonStaking.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; +pragma abicoder v2; + +import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; +import { IHorizonStakingExtension } from "./IHorizonStakingExtension.sol"; + +interface IHorizonStaking is IHorizonStakingBase, IHorizonStakingExtension {} diff --git a/packages/horizon/contracts/IHorizonStakingBase.sol b/packages/horizon/contracts/IHorizonStakingBase.sol new file mode 100644 index 000000000..1fc539f96 --- /dev/null +++ b/packages/horizon/contracts/IHorizonStakingBase.sol @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; +pragma abicoder v2; + +import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; + +interface IHorizonStakingBase is IHorizonStakingTypes { + /** + * @dev Emitted when `serviceProvider` stakes `tokens` amount. + */ + event StakeDeposited(address indexed serviceProvider, uint256 tokens); + + /** + * @dev Emitted when `serviceProvider` withdraws `tokens` amount. + */ + event StakeWithdrawn(address indexed serviceProvider, uint256 tokens); + + /** + * @dev Emitted when `serviceProvider` locks `tokens` amount until `until`. + */ + event StakeLocked(address indexed serviceProvider, uint256 tokens, uint256 until); + + /** + * @dev Emitted when a service provider provisions staked tokens to a verifier + */ + event ProvisionCreated( + address indexed serviceProvider, + address indexed verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + /** + * @dev Emitted when a service provider increases the tokens in a provision + */ + event ProvisionIncreased(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + /** + * @dev Emitted when a thawing request is initiated by a service provider + */ + event ProvisionThawInitiated( + address indexed serviceProvider, + address indexed verifier, + uint256 tokens, + uint64 thawingUntil, + bytes32 indexed thawRequestId + ); + + /** + * @dev Emitted when a service provider removes tokens from a provision after thawing + */ + event ProvisionThawFulfilled( + address indexed serviceProvider, + address indexed verifier, + uint256 tokens, + bytes32 indexed thawRequestId + ); + + event ProvisionSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event DelegationSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event DelegationSlashingSkipped(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event VerifierCutSent( + address indexed serviceProvider, + address indexed verifier, + address indexed destination, + uint256 tokens + ); + + event TokensDelegated( + address indexed serviceProvider, + address indexed verifier, + address indexed delegator, + uint256 tokens + ); + + event TokensUndelegated( + address indexed serviceProvider, + address indexed verifier, + address indexed delegator, + uint256 tokens + ); + + event DelegatedTokensWithdrawn( + address indexed serviceProvider, + address indexed verifier, + address indexed delegator, + uint256 tokens + ); + + event DelegationSlashingEnabled(bool enabled); + + event AllowedLockedVerifierSet(address verifier, bool allowed); + + event TokensAddedToDelegationPool(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event ProvisionParametersStaged( + address indexed serviceProvider, + address indexed verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + event ProvisionParametersSet( + address indexed serviceProvider, + address indexed verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + // deposit stake + function stake(uint256 _tokens) external; + + function stakeTo(address _serviceProvider, uint256 _tokens) external; + + // can be called by anyone if the indexer has provisioned stake to this verifier + function stakeToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external; + + // create a provision + function provision( + address _serviceProvider, + address _verifier, + uint256 _tokens, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) external; + + /** + * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period + * and will be slashable by the verifier. This is the main mechanism to provision stake to a data + * service, where the data service is the verifier. Only authorized verifiers can be used. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param _tokens The amount of tokens that will be locked and slashable + * @param _maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param _thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + */ + function provisionLocked( + address _serviceProvider, + address _verifier, + uint256 _tokens, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) external; + + // initiate a thawing to remove tokens from a provision + function thaw(address _serviceProvider, address _verifier, uint256 _tokens) external returns (bytes32); + + // add more tokens from idle stake to an existing provision + function addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external; + + // moves thawed stake from a provision back into the provider's available stake + function deprovision(address _serviceProvider, address _verifier, uint256 _tokens) external; + + // moves thawed stake from one provision into another provision + function reprovision( + address _serviceProvider, + address _oldVerifier, + address _newVerifier, + uint256 _tokens + ) external; + + // moves thawed stake back to the owner's account - stake is removed from the protocol + function unstake(uint256 _tokens) external; + + // delegate tokens to a provider on a data service + function delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) external; + + // undelegate (thaw) delegated tokens from a provision + function undelegate(address _serviceProvider, address _verifier, uint256 _shares) external; + + // withdraw delegated tokens after thawing + function withdrawDelegated( + address _serviceProvider, + address _verifier, + address _newServiceProvider, + uint256 _minSharesForNewProvider + ) external; + + function slash( + address _serviceProvider, + uint256 _tokens, + uint256 _verifierCutAmount, + address _verifierCutDestination + ) external; + + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address _serviceProvider) external view returns (uint256 tokens); + + /** + * @notice Withdraw indexer tokens once the thawing period has passed. + * @dev This is only needed during the transition period while we still have + * a global lock. After that, unstake() will also withdraw. + */ + function withdraw() external; + + function setDelegationSlashingEnabled(bool _enabled) external; + + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param _operator The address to check for auth + * @param _serviceProvider The service provider on behalf of whom they're claiming to act + * @param _verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized(address _operator, address _serviceProvider, address _verifier) external view returns (bool); + + function getProviderTokensAvailable(address _serviceProvider, address _verifier) external view returns (uint256); + function setMaxThawingPeriod(uint64 _maxThawingPeriod) external; + + function setAllowedLockedVerifier(address _verifier, bool _allowed) external; + + /** + * @notice Add tokens to a delegation pool (without getting shares). + * Used by data services to pay delegation fees/rewards. + * @param _serviceProvider The service provider address + * @param _verifier The verifier address for which the tokens are provisioned + * @param _tokens The amount of tokens to add to the delegation pool + */ + function addToDelegationPool(address _serviceProvider, address _verifier, uint256 _tokens) external; + + function setProvisionParameters( + address _serviceProvider, + address _verifier, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) external; + + function acceptProvisionParameters(address _serviceProvider) external; +} diff --git a/packages/horizon/contracts/IHorizonStakingExtension.sol b/packages/horizon/contracts/IHorizonStakingExtension.sol new file mode 100644 index 000000000..546f9fefa --- /dev/null +++ b/packages/horizon/contracts/IHorizonStakingExtension.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; +pragma abicoder v2; + +import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; + +interface IHorizonStakingExtension { + /** + * @dev Emitted when an operator is allowed or denied by a service provider for a particular data service + */ + event OperatorSet(address indexed serviceProvider, address indexed operator, address verifier, bool allowed); + + event DelegationFeeCutSet( + address indexed serviceProvider, + address indexed verifier, + uint256 feeType, + uint256 feeCut + ); + + function getStake(address serviceProvider) external view returns (uint256); + + function getDelegatedTokensAvailable(address _serviceProvider, address _verifier) external view returns (uint256); + function getTokensAvailable( + address _serviceProvider, + address _verifier, + uint32 _delegationRatio + ) external view returns (uint256); + + function getServiceProvider( + address serviceProvider + ) external view returns (IHorizonStakingTypes.ServiceProvider memory); + + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @param _operator Address to authorize or unauthorize + * @param _verifier The verifier / data service on which they'll be allowed to operate + * @param _allowed Whether the operator is authorized or not + */ + function setOperator(address _operator, address _verifier, bool _allowed) external; + + // for vesting contracts + function setOperatorLocked(address _operator, address _verifier, bool _allowed) external; + + function getMaxThawingPeriod() external view returns (uint64); + + function getDelegationPool( + address _serviceProvider, + address _verifier + ) external view returns (IHorizonStakingTypes.DelegationPool memory); + function getDelegation( + address _delegator, + address _serviceProvider, + address _verifier + ) external view returns (IHorizonStakingTypes.Delegation memory); + function getThawRequest(bytes32 _thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory); + function getProvision( + address _serviceProvider, + address _verifier + ) external view returns (IHorizonStakingTypes.Provision memory); + + function setDelegationFeeCut( + address _serviceProvider, + address _verifier, + uint256 _feeType, + uint256 _feeCut + ) external; + + function getDelegationFeeCut( + address _serviceProvider, + address _verifier, + uint256 _feeType + ) external view returns (uint256); +} diff --git a/packages/horizon/contracts/IHorizonStakingTypes.sol b/packages/horizon/contracts/IHorizonStakingTypes.sol new file mode 100644 index 000000000..f58a004b7 --- /dev/null +++ b/packages/horizon/contracts/IHorizonStakingTypes.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; +pragma abicoder v2; + +interface IHorizonStakingTypes { + struct Provision { + // service provider tokens in the provision + uint256 tokens; + // service provider tokens that are being thawed (and will stop being slashable soon) + uint256 tokensThawing; + // shares representing the thawing tokens + uint256 sharesThawing; + // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed + uint32 maxVerifierCut; + // time, in seconds, tokens must thaw before being withdrawn + uint64 thawingPeriod; + uint64 createdAt; + bytes32 firstThawRequestId; + bytes32 lastThawRequestId; + uint256 nThawRequests; + // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed + uint32 maxVerifierCutPending; + // time, in seconds, tokens must thaw before being withdrawn + uint64 thawingPeriodPending; + } + + struct ServiceProvider { + // Tokens on the provider stake (staked by the provider) + uint256 tokensStaked; + // tokens used in a provision + uint256 tokensProvisioned; + // Next nonce to be used to generate thaw request IDs + uint256 nextThawRequestNonce; + } + + struct DelegationPoolInternal { + uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase + uint32 __DEPRECATED_indexingRewardCut; // in PPM + uint32 __DEPRECATED_queryFeeCut; // in PPM + uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated + uint256 tokens; // Total tokens as pool reserves + uint256 shares; // Total shares minted in the pool + mapping(address => Delegation) delegators; // Mapping of delegator => Delegation + uint256 tokensThawing; // Tokens thawing in the pool + uint256 sharesThawing; // Shares representing the thawing tokens + } + + struct DelegationPool { + uint256 tokens; // Total tokens as pool reserves + uint256 shares; // Total shares minted in the pool + uint256 tokensThawing; // Tokens thawing in the pool + uint256 sharesThawing; // Shares representing the thawing tokens + } + + struct Delegation { + uint256 shares; // Shares owned by a delegator in the pool + uint256 __DEPRECATED_tokensLocked; // Tokens locked for undelegation + uint256 __DEPRECATED_tokensLockedUntil; // Epoch when locked tokens can be withdrawn + bytes32 firstThawRequestId; + bytes32 lastThawRequestId; + uint256 nThawRequests; + uint256 nextThawRequestNonce; + } + + struct ThawRequest { + // shares that represent the tokens being thawed + uint256 shares; + // the timestamp when the thawed funds can be removed from the provision + uint64 thawingUntil; + // id of the next thaw request in the linked list + bytes32 next; + } + + // the new "Indexer" struct + struct ServiceProviderInternal { + // Tokens on the Service Provider stake (staked by the provider) + uint256 tokensStaked; + // Tokens used in allocations + uint256 __DEPRECATED_tokensAllocated; + // Tokens locked for withdrawal subject to thawing period + uint256 __DEPRECATED_tokensLocked; + // Block when locked tokens can be withdrawn + uint256 __DEPRECATED_tokensLockedUntil; + // tokens used in a provision + uint256 tokensProvisioned; + // Next nonce to be used to generate thaw request IDs + uint256 nextThawRequestNonce; + } +} diff --git a/packages/horizon/contracts/IManaged.sol b/packages/horizon/contracts/IManaged.sol new file mode 100644 index 000000000..5aa086ba7 --- /dev/null +++ b/packages/horizon/contracts/IManaged.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; +pragma abicoder v2; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; + +/** + * @title Managed Interface + * @dev Interface for contracts that can be managed by a controller. + */ +interface IManaged { + /** + * @notice (Deprecated) Set the controller that manages this contract + * @dev Only the current controller can set a new controller + * @param _controller Address of the new controller + */ + function setController(address _controller) external; + + /** + * @notice Get the Controller that manages this contract + * @return The Controller as an IController interface + */ + function controller() external view returns (IController); +} diff --git a/packages/horizon/contracts/IStakingBackwardsCompatibility.sol b/packages/horizon/contracts/IStakingBackwardsCompatibility.sol new file mode 100644 index 000000000..43c93662a --- /dev/null +++ b/packages/horizon/contracts/IStakingBackwardsCompatibility.sol @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; +pragma abicoder v2; + +/** + * @title Base interface for the Staking contract. + * @dev This interface includes only what's implemented in the base Staking contract. + * It does not include the L1 and L2 specific functionality. It also does not include + * several functions that are implemented in the StakingExtension contract, and are called + * via delegatecall through the fallback function. See IStaking.sol for an interface + * that includes the full functionality. + */ +interface IStakingBackwardsCompatibility { + /** + * @dev Emitted when `delegator` delegated `tokens` to the `serviceProvider`, the delegator + * gets `shares` for the delegation pool proportionally to the tokens staked. + * This event is here for backwards compatibility, the tokens are delegated + * on the subgraph data service provision. + */ + event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); + + /** + * @dev Allocate GRT tokens for the purpose of serving queries of a subgraph deployment + * An allocation is created in the allocate() function and closed in closeAllocation() + */ + struct Allocation { + address indexer; + bytes32 subgraphDeploymentID; + uint256 tokens; // Tokens allocated to a SubgraphDeployment + uint256 createdAtEpoch; // Epoch when it was created + uint256 closedAtEpoch; // Epoch when it was closed + uint256 collectedFees; // Collected fees for the allocation + uint256 __DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase + uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc + uint256 distributedRebates; // Collected rebates that have been rebated + } + /** + * @dev Emitted when `serviceProvider` stakes `tokens` amount. + */ + event StakeDeposited(address indexed serviceProvider, uint256 tokens); + + /** + * @dev Emitted when `serviceProvider` withdraws `tokens` amount. + */ + event StakeWithdrawn(address indexed serviceProvider, uint256 tokens); + + /** + * @dev Emitted when `serviceProvider` locks `tokens` amount until `until`. + */ + event StakeLocked(address indexed serviceProvider, uint256 tokens, uint256 until); + + /** + * @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`. + * An amount of `tokens` get unallocated from `subgraphDeploymentID`. + * This event also emits the POI (proof of indexing) submitted by the indexer. + * `isPublic` is true if the sender was someone other than the indexer. + */ + event AllocationClosed( + address indexed indexer, + bytes32 indexed subgraphDeploymentID, + uint256 epoch, + uint256 tokens, + address indexed allocationID, + address sender, + bytes32 poi, + bool isPublic + ); + + /** + * @dev Emitted when `indexer` collects a rebate on `subgraphDeploymentID` for `allocationID`. + * `epoch` is the protocol epoch the rebate was collected on + * The rebate is for `tokens` amount which are being provided by `assetHolder`; `queryFees` + * is the amount up for rebate after `curationFees` are distributed and `protocolTax` is burnt. + * `queryRebates` is the amount distributed to the `indexer` with `delegationFees` collected + * and sent to the delegation pool. + */ + event RebateCollected( + address assetHolder, + address indexed indexer, + bytes32 indexed subgraphDeploymentID, + address indexed allocationID, + uint256 epoch, + uint256 tokens, + uint256 protocolTax, + uint256 curationFees, + uint256 queryFees, + uint256 queryRebates, + uint256 delegationRewards + ); + + /** + * @dev Emitted when `indexer` set `operator` access in the legacy contract, + * which now means only for the subgraph data service. + */ + event SetOperator(address indexed indexer, address indexed operator, bool allowed); + + /** + * @dev Possible states an allocation can be. + * States: + * - Null = indexer == address(0) + * - Active = not Null && tokens > 0 + * - Closed = Active && closedAtEpoch != 0 + */ + enum AllocationState { + Null, + Active, + Closed + } + + /** + * @notice Set the address of the counterpart (L1 or L2) staking contract. + * @dev This function can only be called by the governor. + * @param _counterpart Address of the counterpart staking contract in the other chain, without any aliasing. + */ + function setCounterpartStakingAddress(address _counterpart) external; + + /** + * @notice Close an allocation and free the staked tokens. + * To be eligible for rewards a proof of indexing must be presented. + * Presenting a bad proof is subject to slashable condition. + * To opt out of rewards set _poi to 0x0 + * @param _allocationID The allocation identifier + * @param _poi Proof of indexing submitted for the allocated period + */ + function closeAllocation(address _allocationID, bytes32 _poi) external; + + /** + * @notice Collect query fees from state channels and assign them to an allocation. + * Funds received are only accepted from a valid sender. + * @dev To avoid reverting on the withdrawal from channel flow this function will: + * 1) Accept calls with zero tokens. + * 2) Accept calls after an allocation passed the dispute period, in that case, all + * the received tokens are burned. + * @param _tokens Amount of tokens to collect + * @param _allocationID Allocation where the tokens will be assigned + */ + function collect(uint256 _tokens, address _allocationID) external; + + /** + * @notice Return true if operator is allowed for indexer. + * @param _operator Address of the operator + * @param _indexer Address of the indexer + * @return True if operator is allowed for indexer, false otherwise + */ + function isOperator(address _operator, address _indexer) external view returns (bool); + + /** + * @notice Getter that returns if an indexer has any stake. + * @param _indexer Address of the indexer + * @return True if indexer has staked tokens + */ + function hasStake(address _indexer) external view returns (bool); + + /** + * @notice Get the total amount of tokens staked by the indexer. + * @param _indexer Address of the indexer + * @return Amount of tokens staked by the indexer + */ + function getIndexerStakedTokens(address _indexer) external view returns (uint256); + + /** + * @notice Return the allocation by ID. + * @param _allocationID Address used as allocation identifier + * @return Allocation data + */ + function getAllocation(address _allocationID) external view returns (Allocation memory); + + /** + * @notice Return the current state of an allocation + * @param _allocationID Allocation identifier + * @return AllocationState enum with the state of the allocation + */ + function getAllocationState(address _allocationID) external view returns (AllocationState); + + /** + * @notice Return if allocationID is used. + * @param _allocationID Address used as signer by the indexer for an allocation + * @return True if allocationID already used + */ + function isAllocation(address _allocationID) external view returns (bool); + + /** + * @notice Return the total amount of tokens allocated to subgraph. + * @param _subgraphDeploymentID Deployment ID for the subgraph + * @return Total tokens allocated to subgraph + */ + function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view returns (uint256); +} diff --git a/packages/horizon/contracts/Managed.sol b/packages/horizon/contracts/Managed.sol new file mode 100644 index 000000000..858156bbd --- /dev/null +++ b/packages/horizon/contracts/Managed.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; +import { IManaged } from "./IManaged.sol"; +import { GraphDirectory } from "./GraphDirectory.sol"; + +/** + * @title Graph Managed contract + * @dev The Managed contract provides an interface to interact with the Controller. + * Inspired by Livepeer: + * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol + */ +abstract contract Managed is IManaged, GraphDirectory { + // -- State -- + + /// Controller that manages this contract + IController private __DEPRECATED_controller; + /// @dev Cache for the addresses of the contracts retrieved from the controller + mapping(bytes32 => address) private __DEPRECATED_addressCache; + /// @dev Gap for future storage variables + uint256[10] private __gap; + + // -- Events -- + + /// Emitted when a contract parameter has been updated + event ParameterUpdated(string param); + /// (Deprecated) Emitted when the controller address has been set + event SetController(address controller); + + ///(Deprecated) Emitted when contract with `nameHash` is synced to `contractAddress`. + event ContractSynced(bytes32 indexed nameHash, address contractAddress); + + error ManagedSetControllerDeprecated(); + + constructor(address _controller) GraphDirectory(_controller) {} + + function controller() public view override returns (IController) { + return IController(CONTROLLER); + } + + /** + * @dev Revert if the controller is paused or partially paused + */ + function _notPartialPaused() internal view { + require(!controller().paused(), "Paused"); + require(!controller().partialPaused(), "Partial-paused"); + } + + /** + * @dev Revert if the controller is paused + */ + function _notPaused() internal view virtual { + require(!controller().paused(), "Paused"); + } + + /** + * @dev Revert if the caller is not the governor + */ + function _onlyGovernor() internal view { + require(msg.sender == controller().getGovernor(), "Only Controller governor"); + } + + /** + * @dev Revert if the caller is not the Controller + */ + function _onlyController() internal view { + require(msg.sender == CONTROLLER, "Caller must be Controller"); + } + + /** + * @dev Revert if the controller is paused or partially paused + */ + modifier notPartialPaused() { + _notPartialPaused(); + _; + } + + /** + * @dev Revert if the controller is paused + */ + modifier notPaused() { + _notPaused(); + _; + } + + /** + * @dev Revert if the caller is not the Controller + */ + modifier onlyController() { + _onlyController(); + _; + } + + /** + * @dev Revert if the caller is not the governor + */ + modifier onlyGovernor() { + _onlyGovernor(); + _; + } + + /** + * @notice Set Controller. Deprecated, will revert. + */ + function setController(address) external view override onlyController { + revert ManagedSetControllerDeprecated(); + } +} diff --git a/packages/horizon/contracts/SimpleTest.sol b/packages/horizon/contracts/SimpleTest.sol deleted file mode 100644 index 5cc28d9cc..000000000 --- a/packages/horizon/contracts/SimpleTest.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.4.0 <0.9.0; - -import { Test } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; - -contract SimpleTest is Test { - function test() external pure returns (uint256) { - return 42; - } -} diff --git a/packages/horizon/contracts/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/StakingBackwardsCompatibility.sol new file mode 100644 index 000000000..6e6261bd4 --- /dev/null +++ b/packages/horizon/contracts/StakingBackwardsCompatibility.sol @@ -0,0 +1,508 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +import { Multicall } from "@graphprotocol/contracts/contracts/base/Multicall.sol"; +import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; +import { TokenUtils } from "./utils/TokenUtils.sol"; +import { IGraphToken } from "./IGraphToken.sol"; +import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; +import { MathUtils } from "./utils/MathUtils.sol"; +import { Managed } from "./Managed.sol"; +import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; +import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; +import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; +import { ExponentialRebates } from "./utils/ExponentialRebates.sol"; +import { IStakingBackwardsCompatibility } from "./IStakingBackwardsCompatibility.sol"; + +/** + * @title Base Staking contract + * @dev 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 + * and L2Staking on Arbitrum. + * Note that this contract delegates part of its functionality to a StakingExtension contract. + * This is due to the 24kB contract size limit on Ethereum. + */ +abstract contract StakingBackwardsCompatibility is + HorizonStakingV1Storage, + GraphUpgradeable, + Multicall, + IStakingBackwardsCompatibility +{ + /// @dev 100% in parts per million + uint32 internal constant MAX_PPM = 1000000; + + address public immutable SUBGRAPH_DATA_SERVICE_ADDRESS; + + address public immutable EXPONENTIAL_REBATES_ADDRESS; + + constructor( + address _controller, + address _subgraphDataServiceAddress, + address _exponentialRebatesAddress + ) Managed(_controller) { + SUBGRAPH_DATA_SERVICE_ADDRESS = _subgraphDataServiceAddress; + EXPONENTIAL_REBATES_ADDRESS = _exponentialRebatesAddress; + } + + /** + * @notice Set the address of the counterpart (L1 or L2) staking contract. + * @dev This function can only be called by the governor. + * TODO: Remove after L2 transition period + * @param _counterpart Address of the counterpart staking contract in the other chain, without any aliasing. + */ + function setCounterpartStakingAddress(address _counterpart) external override onlyGovernor { + counterpartStakingAddress = _counterpart; + emit ParameterUpdated("counterpartStakingAddress"); + } + + /** + * @notice Close an allocation and free the staked tokens. + * To be eligible for rewards a proof of indexing must be presented. + * Presenting a bad proof is subject to slashable condition. + * To opt out of rewards set _poi to 0x0 + * @dev TODO: Remove after Horizon transition period + * @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. + * 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. + * TODO: Remove after Horizon transition period + * @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 + require(_allocationID != address(0), "!alloc"); + + // Allocation must exist + AllocationState allocState = _getAllocationState(_allocationID); + require(allocState != AllocationState.Null, "!collect"); + + // If the query fees are zero, we don't want to revert + // but we also don't need to do anything, so just return + if (_tokens == 0) { + return; + } + + Allocation storage alloc = __DEPRECATED_allocations[_allocationID]; + bytes32 subgraphDeploymentID = alloc.subgraphDeploymentID; + + uint256 queryFees = _tokens; // Tokens collected from the channel + uint256 protocolTax = 0; // Tokens burnt as protocol tax + uint256 curationFees = 0; // Tokens distributed to curators as curation fees + uint256 queryRebates = 0; // Tokens to distribute to indexer + uint256 delegationRewards = 0; // Tokens to distribute to delegators + + { + // -- Pull tokens from the sender -- + IGraphToken graphToken = _graphToken(); + TokenUtils.pullTokens(graphToken, msg.sender, queryFees); + + // -- Collect protocol tax -- + protocolTax = _collectTax(queryFees, __DEPRECATED_protocolPercentage); + queryFees = queryFees - protocolTax; + + // -- Collect curation fees -- + // Only if the subgraph deployment is curated + curationFees = _collectCurationFees(subgraphDeploymentID, queryFees, __DEPRECATED_curationPercentage); + queryFees = queryFees - curationFees; + + // -- Process rebate reward -- + // Using accumulated fees and subtracting previously distributed rebates + // allows for multiple vouchers to be collected while following the rebate formula + alloc.collectedFees = alloc.collectedFees + queryFees; + + // No rebates if indexer has no stake or if lambda is zero + uint256 newRebates = (alloc.tokens == 0 || __DEPRECATED_lambdaNumerator == 0) + ? 0 + : ExponentialRebates(EXPONENTIAL_REBATES_ADDRESS).exponentialRebates( + alloc.collectedFees, + alloc.tokens, + __DEPRECATED_alphaNumerator, + __DEPRECATED_alphaDenominator, + __DEPRECATED_lambdaNumerator, + __DEPRECATED_lambdaDenominator + ); + + // -- Ensure rebates to distribute are within bounds -- + // Indexers can become under or over rebated if rebate parameters (alpha, lambda) + // change between successive collect calls for the same allocation + + // Ensure rebates to distribute are not negative (indexer is over-rebated) + queryRebates = MathUtils.diffOrZero(newRebates, alloc.distributedRebates); + + // Ensure rebates to distribute are not greater than available (indexer is under-rebated) + queryRebates = MathUtils.min(queryRebates, queryFees); + + // -- Burn rebates remanent -- + TokenUtils.burnTokens(graphToken, queryFees - queryRebates); + + // -- Distribute rebates -- + if (queryRebates > 0) { + alloc.distributedRebates = alloc.distributedRebates + queryRebates; + + // -- Collect delegation rewards into the delegation pool -- + delegationRewards = _collectDelegationQueryRewards(alloc.indexer, queryRebates); + queryRebates = queryRebates - delegationRewards; + + // -- Transfer or restake rebates -- + _sendRewards(queryRebates, alloc.indexer, __DEPRECATED_rewardsDestination[alloc.indexer] == address(0)); + } + } + + emit RebateCollected( + msg.sender, + alloc.indexer, + subgraphDeploymentID, + _allocationID, + _epochManager().currentEpoch(), + _tokens, + protocolTax, + curationFees, + queryFees, + queryRebates, + delegationRewards + ); + } + + /** + * @notice Return if allocationID is used. + * @dev TODO: Remove after Horizon transition period + * @param _allocationID Address used as signer by the indexer for an allocation + * @return True if allocationID already used + */ + function isAllocation(address _allocationID) external view override returns (bool) { + return _getAllocationState(_allocationID) != AllocationState.Null; + } + + /** + * @notice Return the allocation by ID. + * @dev TODO: Remove after Horizon transition period + * @param _allocationID Address used as allocation identifier + * @return Allocation data + */ + function getAllocation(address _allocationID) external view override returns (Allocation memory) { + return __DEPRECATED_allocations[_allocationID]; + } + + /** + * @notice Return the current state of an allocation + * @dev TODO: Remove after Horizon transition period + * @param _allocationID Allocation identifier + * @return AllocationState enum with the state of the allocation + */ + 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 + */ + function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { + return __DEPRECATED_subgraphAllocations[_subgraphDeploymentID]; + } + + /** + * @notice (Legacy) Return true if operator is allowed for the service provider on the subgraph data service. + * @dev TODO: Delete after the transition period + * @param _operator Address of the operator + * @param _serviceProvider Address of the service provider + * @return True if operator is allowed for indexer, false otherwise + */ + function isOperator(address _operator, address _serviceProvider) public view override returns (bool) { + return legacyOperatorAuth[_serviceProvider][_operator]; + } + + /** + * @notice Get the total amount of tokens staked by the indexer. + * @param _indexer Address of the indexer + * @return Amount of tokens staked by the indexer + */ + function getIndexerStakedTokens(address _indexer) external view override returns (uint256) { + return serviceProviders[_indexer].tokensStaked; + } + + /** + * @notice Getter that returns if an indexer has any stake. + * @param _indexer Address of the indexer + * @return True if indexer has staked tokens + */ + function hasStake(address _indexer) external view override returns (bool) { + return serviceProviders[_indexer].tokensStaked > 0; + } + + /** + * @dev Close an allocation and free the staked tokens. + * @param _allocationID The allocation identifier + * @param _poi Proof of indexing submitted for the allocated period + */ + function _closeAllocation(address _allocationID, bytes32 _poi) private { + // Allocation must exist and be active + AllocationState allocState = _getAllocationState(_allocationID); + require(allocState == AllocationState.Active, "!active"); + + // Get allocation + Allocation memory alloc = __DEPRECATED_allocations[_allocationID]; + + // Validate that an allocation cannot be closed before one epoch + alloc.closedAtEpoch = _epochManager().currentEpoch(); + uint256 epochs = MathUtils.diffOrZero(alloc.closedAtEpoch, alloc.createdAtEpoch); + + // Indexer or operator can close an allocation + // Anyone is allowed to close ONLY under two concurrent conditions + // - After maxAllocationEpochs passed + // - When the allocation is for non-zero amount of tokens + bool isIndexer = isOperator(alloc.indexer, SUBGRAPH_DATA_SERVICE_ADDRESS); + if (epochs <= __DEPRECATED_maxAllocationEpochs || alloc.tokens == 0) { + require(isIndexer, "!auth"); + } + + // Close the allocation + __DEPRECATED_allocations[_allocationID].closedAtEpoch = alloc.closedAtEpoch; + + // -- Rewards Distribution -- + + // Process non-zero-allocation rewards tracking + if (alloc.tokens > 0) { + // Distribute rewards if proof of indexing was presented by the indexer or operator + if (isIndexer && _poi != 0) { + _distributeRewards(_allocationID, alloc.indexer); + } else { + _updateRewards(alloc.subgraphDeploymentID); + } + + // Free allocated tokens from use + serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated = + serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated - + alloc.tokens; + + // Track total allocations per subgraph + // Used for rewards calculations + __DEPRECATED_subgraphAllocations[alloc.subgraphDeploymentID] = + __DEPRECATED_subgraphAllocations[alloc.subgraphDeploymentID] - + alloc.tokens; + } + + emit AllocationClosed( + alloc.indexer, + alloc.subgraphDeploymentID, + alloc.closedAtEpoch, + alloc.tokens, + _allocationID, + msg.sender, + _poi, + !isIndexer + ); + } + + /** + * @dev 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 + * @return Amount of delegation rewards + */ + function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { + uint256 delegationRewards = 0; + DelegationPoolInternal storage pool = legacyDelegationPools[_indexer]; + if (pool.tokens > 0 && pool.__DEPRECATED_queryFeeCut < MAX_PPM) { + uint256 indexerCut = (uint256(pool.__DEPRECATED_queryFeeCut) * _tokens) / MAX_PPM; + delegationRewards = _tokens - indexerCut; + pool.tokens = pool.tokens + delegationRewards; + } + return delegationRewards; + } + + /** + * @dev 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 + * @return Amount of delegation rewards + */ + function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { + uint256 delegationRewards = 0; + DelegationPoolInternal storage pool = legacyDelegationPools[_indexer]; + if (pool.tokens > 0 && pool.__DEPRECATED_indexingRewardCut < MAX_PPM) { + uint256 indexerCut = (uint256(pool.__DEPRECATED_indexingRewardCut) * _tokens) / MAX_PPM; + delegationRewards = _tokens - indexerCut; + pool.tokens = pool.tokens + delegationRewards; + } + return delegationRewards; + } + + /** + * @dev Collect the curation fees for a subgraph deployment from an amount of tokens. + * This function transfer curation fees to the Curation contract by calling Curation.collect + * @param _subgraphDeploymentID Subgraph deployment to which the curation fees are related + * @param _tokens Total tokens received used to calculate the amount of fees to collect + * @param _curationPercentage Percentage of tokens to collect as fees + * @return Amount of curation fees + */ + function _collectCurationFees( + bytes32 _subgraphDeploymentID, + uint256 _tokens, + uint256 _curationPercentage + ) private returns (uint256) { + if (_tokens == 0) { + return 0; + } + + ICuration curation = _curation(); + bool isCurationEnabled = _curationPercentage > 0 && address(curation) != address(0); + + if (isCurationEnabled && curation.isCurated(_subgraphDeploymentID)) { + // Calculate the tokens after curation fees first, and subtact that, + // to prevent curation fees from rounding down to zero + uint256 tokensAfterCurationFees = ((uint256(MAX_PPM) - _curationPercentage) * _tokens) / MAX_PPM; + uint256 curationFees = _tokens - tokensAfterCurationFees; + if (curationFees > 0) { + // Transfer and call collect() + // This function transfer tokens to a trusted protocol contracts + // Then we call collect() to do the transfer bookeeping + _rewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); + TokenUtils.pushTokens(_graphToken(), address(curation), curationFees); + curation.collect(_subgraphDeploymentID, curationFees); + } + return curationFees; + } + return 0; + } + + /** + * @dev Collect tax to burn for an amount of tokens. + * @param _tokens Total tokens received used to calculate the amount of tax to collect + * @param _percentage Percentage of tokens to burn as tax + * @return Amount of tax charged + */ + function _collectTax(uint256 _tokens, uint256 _percentage) private returns (uint256) { + // Calculate tokens after tax first, and subtract that, + // to prevent the tax from rounding down to zero + uint256 tokensAfterTax = ((uint256(MAX_PPM) - _percentage) * _tokens) / MAX_PPM; + uint256 tax = _tokens - tokensAfterTax; + TokenUtils.burnTokens(_graphToken(), tax); // Burn tax if any + return tax; + } + + /** + * @dev 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 + */ + function _updateRewards(bytes32 _subgraphDeploymentID) private returns (uint256) { + IRewardsManager rewardsManager = _rewardsManager(); + if (address(rewardsManager) == address(0)) { + return 0; + } + return rewardsManager.onSubgraphAllocationUpdate(_subgraphDeploymentID); + } + + /** + * @dev Assign rewards for the closed allocation to indexer and delegators. + * @param _allocationID Allocation + * @param _indexer Address of the indexer that did the allocation + */ + function _distributeRewards(address _allocationID, address _indexer) private { + IRewardsManager rewardsManager = _rewardsManager(); + if (address(rewardsManager) == address(0)) { + return; + } + + // Automatically triggers update of rewards snapshot as allocation will change + // after this call. Take rewards mint tokens for the Staking contract to distribute + // between indexer and delegators + uint256 totalRewards = rewardsManager.takeRewards(_allocationID); + if (totalRewards == 0) { + return; + } + + // Calculate delegation rewards and add them to the delegation pool + uint256 delegationRewards = _collectDelegationIndexingRewards(_indexer, totalRewards); + uint256 indexerRewards = totalRewards - delegationRewards; + + // Send the indexer rewards + _sendRewards(indexerRewards, _indexer, __DEPRECATED_rewardsDestination[_indexer] == address(0)); + } + + /** + * @dev Send rewards to the appropriate destination. + * @param _amount Number of rewards tokens + * @param _beneficiary Address of the beneficiary of rewards + * @param _restake Whether to restake or not + */ + function _sendRewards(uint256 _amount, address _beneficiary, bool _restake) private { + if (_amount == 0) return; + + if (_restake) { + // Restake to place fees into the indexer stake + _stake(_beneficiary, _amount); + } else { + // Transfer funds to the beneficiary's designated rewards destination if set + address destination = __DEPRECATED_rewardsDestination[_beneficiary]; + TokenUtils.pushTokens(_graphToken(), destination == address(0) ? _beneficiary : destination, _amount); + } + } + + /** + * @dev Return the current state of an allocation + * @param _allocationID Allocation identifier + * @return AllocationState enum with the state of the allocation + */ + function _getAllocationState(address _allocationID) private view returns (AllocationState) { + Allocation storage alloc = __DEPRECATED_allocations[_allocationID]; + + if (alloc.indexer == address(0)) { + return AllocationState.Null; + } + + if (alloc.createdAtEpoch != 0 && alloc.closedAtEpoch == 0) { + return AllocationState.Active; + } + + return AllocationState.Closed; + } + + /** + * @dev Stake tokens on the service provider. + * TODO: Move to HorizonStaking after the transition period + * @param _serviceProvider Address of staking party + * @param _tokens Amount of tokens to stake + */ + function _stake(address _serviceProvider, uint256 _tokens) internal { + // Deposit tokens into the indexer stake + serviceProviders[_serviceProvider].tokensStaked = serviceProviders[_serviceProvider].tokensStaked + _tokens; + + emit StakeDeposited(_serviceProvider, _tokens); + } + + function _graphToken() internal view returns (IGraphToken) { + return IGraphToken(GRAPH_TOKEN); + } + + function _curation() internal view returns (ICuration) { + return ICuration(CURATION); + } + + function _rewardsManager() internal view returns (IRewardsManager) { + return IRewardsManager(REWARDS_MANAGER); + } + + function _epochManager() internal view returns (IEpochManager) { + return IEpochManager(EPOCH_MANAGER); + } +} diff --git a/packages/horizon/contracts/mocks/ControllerMock.sol b/packages/horizon/contracts/mocks/ControllerMock.sol new file mode 100644 index 000000000..f8c976cf9 --- /dev/null +++ b/packages/horizon/contracts/mocks/ControllerMock.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; +import { IManaged } from "@graphprotocol/contracts/contracts/governance/IManaged.sol"; + +/** + * @title Graph Controller contract (mock) + * @dev Controller is a registry of contracts for convenience. Inspired by Livepeer: + * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol + */ +contract ControllerMock is IController { + /// @dev Track contract ids to contract proxy address + mapping(bytes32 => address) private _registry; + address public governor; + bool internal _paused; + bool internal _partialPaused; + address internal _pauseGuardian; + + /// Emitted when the proxy address for a protocol contract has been set + event SetContractProxy(bytes32 indexed id, address contractAddress); + + /** + * Constructor for the Controller mock + * @param _governor Address of the governor + */ + constructor(address _governor) { + governor = _governor; + } + + /** + * @notice Getter to access governor + * @return Address of the governor + */ + function getGovernor() external view override returns (address) { + return governor; + } + + // -- 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 override { + require(_contractAddress != address(0), "Contract address must be set"); + _registry[_id] = _contractAddress; + emit SetContractProxy(_id, _contractAddress); + } + + /** + * @notice Unregister a contract address + * @param _id Contract id (keccak256 hash of contract name) + */ + function unsetContractProxy(bytes32 _id) external override { + _registry[_id] = address(0); + emit SetContractProxy(_id, address(0)); + } + + /** + * @notice Get contract proxy address by its id + * @param _id Contract id (keccak256 hash of contract name) + * @return Address of the proxy contract for the provided id + */ + function getContractProxy(bytes32 _id) external view override returns (address) { + return _registry[_id]; + } + + /** + * @notice Update a contract's controller + * @param _id Contract id (keccak256 hash of contract name) + * @param _controller New Controller address + */ + function updateController(bytes32 _id, address _controller) external override { + require(_controller != address(0), "Controller must be set"); + return IManaged(_registry[_id]).setController(_controller); + } + + // -- 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 + */ + function setPartialPaused(bool _toPause) external override { + _partialPaused = _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 + */ + function setPaused(bool _toPause) external override { + _paused = _toPause; + } + + /** + * @notice Change the Pause Guardian + * @param _newPauseGuardian The address of the new Pause Guardian + */ + function setPauseGuardian(address _newPauseGuardian) external override { + require(_newPauseGuardian != address(0), "PauseGuardian must be set"); + _pauseGuardian = _newPauseGuardian; + } + + /** + * @notice Getter to access paused + * @return True if the contracts are paused, false otherwise + */ + 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 + */ + function partialPaused() external view override returns (bool) { + return _partialPaused; + } +} diff --git a/packages/horizon/contracts/utils/ExponentialRebates.sol b/packages/horizon/contracts/utils/ExponentialRebates.sol new file mode 100644 index 000000000..d53efdca3 --- /dev/null +++ b/packages/horizon/contracts/utils/ExponentialRebates.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { LibFixedMath } from "./LibFixedMath.sol"; + +/** + * @title ExponentialRebates contract + * @notice A library to compute query fee rebates using an exponential formula + * @dev This is only used for backwards compatibility in HorizonStaking, and should + * be removed after the transition period. + */ +contract ExponentialRebates { + /// @dev Maximum value of the exponent for which to compute the exponential before clamping to zero. + uint32 private constant MAX_EXPONENT = 15; + + /// @dev The exponential formula used to compute fee-based rewards for + /// staking pools in a given epoch. This function does not perform + /// bounds checking on the inputs, but the following conditions + /// need to be true: + /// 0 <= alphaNumerator / alphaDenominator <= 1 + /// 0 < lambdaNumerator / lambdaDenominator + /// The exponential rebates function has the form: + /// `(1 - alpha * exp ^ (-lambda * stake / fees)) * fees` + /// @param fees Fees generated by indexer in the staking pool. + /// @param stake Stake attributed to the indexer in the staking pool. + /// @param alphaNumerator Numerator of `alpha` in the rebates function. + /// @param alphaDenominator Denominator of `alpha` in the rebates function. + /// @param lambdaNumerator Numerator of `lambda` in the rebates function. + /// @param lambdaDenominator Denominator of `lambda` in the rebates function. + /// @return rewards Rewards owed to the staking pool. + function exponentialRebates( + uint256 fees, + uint256 stake, + uint32 alphaNumerator, + uint32 alphaDenominator, + uint32 lambdaNumerator, + uint32 lambdaDenominator + ) external pure returns (uint256) { + // If alpha is zero indexer gets 100% fees rebate + int256 alpha = LibFixedMath.toFixed(int32(alphaNumerator), int32(alphaDenominator)); + if (alpha == 0) { + return fees; + } + + // No rebates if no fees... + if (fees == 0) { + return 0; + } + + // Award all fees as rebate if the exponent is too large + int256 lambda = LibFixedMath.toFixed(int32(lambdaNumerator), int32(lambdaDenominator)); + int256 exponent = LibFixedMath.mulDiv(lambda, int256(stake), int256(fees)); + if (LibFixedMath.toInteger(exponent) > int256(uint256(MAX_EXPONENT))) { + return fees; + } + + // Compute `1 - alpha * exp ^(-exponent)` + int256 factor = LibFixedMath.sub(LibFixedMath.one(), LibFixedMath.mul(alpha, LibFixedMath.exp(-exponent))); + + // Weight the fees by the factor + return LibFixedMath.uintMul(factor, fees); + } +} diff --git a/packages/horizon/contracts/utils/LibFixedMath.sol b/packages/horizon/contracts/utils/LibFixedMath.sol new file mode 100644 index 000000000..487de84a8 --- /dev/null +++ b/packages/horizon/contracts/utils/LibFixedMath.sol @@ -0,0 +1,389 @@ +/* + + Copyright 2017 Bprotocol Foundation, 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity 0.8.24; + +// solhint-disable indent +/// @dev Signed, fixed-point, 127-bit precision math library. +library LibFixedMath { + // 1 + int256 private constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000); + // 2**255 + int256 private constant MIN_FIXED_VAL = type(int256).min; + // 1^2 (in fixed-point) + int256 private constant FIXED_1_SQUARED = + int256(0x4000000000000000000000000000000000000000000000000000000000000000); + // 1 + int256 private constant LN_MAX_VAL = FIXED_1; + // e ^ -63.875 + int256 private constant LN_MIN_VAL = int256(0x0000000000000000000000000000000000000000000000000000000733048c5a); + // 0 + int256 private constant EXP_MAX_VAL = 0; + // -63.875 + int256 private constant EXP_MIN_VAL = -int256(0x0000000000000000000000000000001ff0000000000000000000000000000000); + + /// @dev Get one as a fixed-point number. + function one() internal pure returns (int256 f) { + f = FIXED_1; + } + + /// @dev Returns the addition of two fixed point numbers, reverting on overflow. + 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. + function sub(int256 a, int256 b) internal pure returns (int256 c) { + if (b == MIN_FIXED_VAL) { + revert("out-of-bounds"); + } + c = _add(a, -b); + } + + /// @dev Returns the multiplication of two fixed point numbers, reverting on overflow. + 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. + 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. + function mulDiv(int256 a, int256 n, int256 d) internal pure returns (int256 c) { + c = _div(_mul(a, n), d); + } + + /// @dev Returns the unsigned integer result of multiplying a fixed-point + /// number with an integer, reverting if the multiplication overflows. + /// Negative results are clamped to zero. + function uintMul(int256 f, uint256 u) internal pure returns (uint256) { + if (int256(u) < int256(0)) { + revert("out-of-bounds"); + } + int256 c = _mul(f, int256(u)); + if (c <= 0) { + return 0; + } + return uint256(uint256(c) >> 127); + } + + /// @dev Returns the absolute value of a fixed point number. + function abs(int256 f) internal pure returns (int256 c) { + if (f == MIN_FIXED_VAL) { + revert("out-of-bounds"); + } + if (f >= 0) { + c = f; + } else { + c = -f; + } + } + + /// @dev Returns 1 / `x`, where `x` is a fixed-point number. + 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. + function toFixed(int256 n) internal pure returns (int256 f) { + f = _mul(n, FIXED_1); + } + + /// @dev Convert signed `n` / `d` to a fixed-point number. + 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. + /// Reverts if `n` is too large to fit in a fixed-point number. + function toFixed(uint256 n) internal pure returns (int256 f) { + if (int256(n) < int256(0)) { + revert("out-of-bounds"); + } + f = _mul(int256(n), FIXED_1); + } + + /// @dev Convert unsigned `n` / `d` to a fixed-point number. + /// Reverts if `n` / `d` is too large to fit in a fixed-point number. + function toFixed(uint256 n, uint256 d) internal pure returns (int256 f) { + if (int256(n) < int256(0)) { + revert("out-of-bounds"); + } + if (int256(d) < int256(0)) { + revert("out-of-bounds"); + } + f = _div(_mul(int256(n), FIXED_1), int256(d)); + } + + /// @dev Convert a fixed-point number to an integer. + 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 + function ln(int256 x) internal pure returns (int256 r) { + if (x > LN_MAX_VAL) { + revert("out-of-bounds"); + } + if (x <= 0) { + revert("too-small"); + } + if (x == FIXED_1) { + return 0; + } + if (x <= LN_MIN_VAL) { + return EXP_MIN_VAL; + } + + int256 y; + int256 z; + int256 w; + unchecked { + // Rewrite the input as a quotient of negative natural exponents and a single residual q, such that 1 < q < 2 + // For example: log(0.3) = log(e^-1 * e^-0.25 * 1.0471028872385522) + // = 1 - 0.25 - log(1 + 0.0471028872385522) + // e ^ -32 + if (x <= int256(0x00000000000000000000000000000000000000000001c8464f76164760000000)) { + r -= int256(0x0000000000000000000000000000001000000000000000000000000000000000); // - 32 + x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000000001c8464f76164760000000); // / e ^ -32 + } + // e ^ -16 + if (x <= int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000)) { + r -= int256(0x0000000000000000000000000000000800000000000000000000000000000000); // - 16 + x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000); // / e ^ -16 + } + // e ^ -8 + if (x <= int256(0x00000000000000000000000000000000000afe10820813d78000000000000000)) { + r -= int256(0x0000000000000000000000000000000400000000000000000000000000000000); // - 8 + x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000afe10820813d78000000000000000); // / e ^ -8 + } + // e ^ -4 + if (x <= int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000)) { + r -= int256(0x0000000000000000000000000000000200000000000000000000000000000000); // - 4 + x = (x * FIXED_1) / int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000); // / e ^ -4 + } + // e ^ -2 + if (x <= int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000)) { + r -= int256(0x0000000000000000000000000000000100000000000000000000000000000000); // - 2 + x = (x * FIXED_1) / int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000); // / e ^ -2 + } + // e ^ -1 + if (x <= int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000)) { + r -= int256(0x0000000000000000000000000000000080000000000000000000000000000000); // - 1 + x = (x * FIXED_1) / int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000); // / e ^ -1 + } + // e ^ -0.5 + if (x <= int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000)) { + r -= int256(0x0000000000000000000000000000000040000000000000000000000000000000); // - 0.5 + x = (x * FIXED_1) / int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000); // / e ^ -0.5 + } + // e ^ -0.25 + if (x <= int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000)) { + r -= int256(0x0000000000000000000000000000000020000000000000000000000000000000); // - 0.25 + x = (x * FIXED_1) / int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000); // / e ^ -0.25 + } + // e ^ -0.125 + if (x <= int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) { + r -= int256(0x0000000000000000000000000000000010000000000000000000000000000000); // - 0.125 + x = (x * FIXED_1) / int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d); // / e ^ -0.125 + } + // `x` is now our residual in the range of 1 <= x <= 2 (or close enough). + + // Add the taylor series for log(1 + z), where z = x - 1 + z = y = x - FIXED_1; + w = (y * y) / FIXED_1; + r += (z * (0x100000000000000000000000000000000 - y)) / 0x100000000000000000000000000000000; + z = (z * w) / FIXED_1; // add y^01 / 01 - y^02 / 02 + r += (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / 0x200000000000000000000000000000000; + z = (z * w) / FIXED_1; // add y^03 / 03 - y^04 / 04 + r += (z * (0x099999999999999999999999999999999 - y)) / 0x300000000000000000000000000000000; + z = (z * w) / FIXED_1; // add y^05 / 05 - y^06 / 06 + r += (z * (0x092492492492492492492492492492492 - y)) / 0x400000000000000000000000000000000; + z = (z * w) / FIXED_1; // add y^07 / 07 - y^08 / 08 + r += (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / 0x500000000000000000000000000000000; + z = (z * w) / FIXED_1; // add y^09 / 09 - y^10 / 10 + r += (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / 0x600000000000000000000000000000000; + z = (z * w) / FIXED_1; // add y^11 / 11 - y^12 / 12 + r += (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / 0x700000000000000000000000000000000; + z = (z * w) / FIXED_1; // add y^13 / 13 - y^14 / 14 + 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 + function exp(int256 x) internal pure returns (int256 r) { + if (x < EXP_MIN_VAL) { + // Saturate to zero below EXP_MIN_VAL. + return 0; + } + if (x == 0) { + return FIXED_1; + } + if (x > EXP_MAX_VAL) { + revert("out-of-bounds"); + } + + // Rewrite the input as a product of natural exponents and a + // single residual q, where q is a number of small magnitude. + // For example: e^-34.419 = e^(-32 - 2 - 0.25 - 0.125 - 0.044) + // = e^-32 * e^-2 * e^-0.25 * e^-0.125 * e^-0.044 + // -> q = -0.044 + + // Multiply with the taylor series for e^q + int256 y; + int256 z; + // q = x % 0.125 (the residual) + z = y = x % 0x0000000000000000000000000000000010000000000000000000000000000000; + z = (z * y) / FIXED_1; + r += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!) + z = (z * y) / FIXED_1; + r += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!) + z = (z * y) / FIXED_1; + r += z * 0x0168244fdac78000; // add y^04 * (20! / 04!) + z = (z * y) / FIXED_1; + r += z * 0x004807432bc18000; // add y^05 * (20! / 05!) + z = (z * y) / FIXED_1; + r += z * 0x000c0135dca04000; // add y^06 * (20! / 06!) + z = (z * y) / FIXED_1; + r += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!) + z = (z * y) / FIXED_1; + r += z * 0x000036e0f639b800; // add y^08 * (20! / 08!) + z = (z * y) / FIXED_1; + r += z * 0x00000618fee9f800; // add y^09 * (20! / 09!) + z = (z * y) / FIXED_1; + r += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!) + z = (z * y) / FIXED_1; + r += z * 0x0000000e30dce400; // add y^11 * (20! / 11!) + z = (z * y) / FIXED_1; + r += z * 0x000000012ebd1300; // add y^12 * (20! / 12!) + z = (z * y) / FIXED_1; + r += z * 0x0000000017499f00; // add y^13 * (20! / 13!) + z = (z * y) / FIXED_1; + r += z * 0x0000000001a9d480; // add y^14 * (20! / 14!) + z = (z * y) / FIXED_1; + r += z * 0x00000000001c6380; // add y^15 * (20! / 15!) + z = (z * y) / FIXED_1; + r += z * 0x000000000001c638; // add y^16 * (20! / 16!) + z = (z * y) / FIXED_1; + r += z * 0x0000000000001ab8; // add y^17 * (20! / 17!) + z = (z * y) / FIXED_1; + r += z * 0x000000000000017c; // add y^18 * (20! / 18!) + z = (z * y) / FIXED_1; + r += z * 0x0000000000000014; // add y^19 * (20! / 19!) + z = (z * y) / FIXED_1; + r += z * 0x0000000000000001; // add y^20 * (20! / 20!) + r = r / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0! + + // Multiply with the non-residual terms. + x = -x; + // e ^ -32 + if ((x & int256(0x0000000000000000000000000000001000000000000000000000000000000000)) != 0) { + r = + (r * int256(0x00000000000000000000000000000000000000f1aaddd7742e56d32fb9f99744)) / + int256(0x0000000000000000000000000043cbaf42a000812488fc5c220ad7b97bf6e99e); // * e ^ -32 + } + // e ^ -16 + if ((x & int256(0x0000000000000000000000000000000800000000000000000000000000000000)) != 0) { + r = + (r * int256(0x00000000000000000000000000000000000afe10820813d65dfe6a33c07f738f)) / + int256(0x000000000000000000000000000005d27a9f51c31b7c2f8038212a0574779991); // * e ^ -16 + } + // e ^ -8 + if ((x & int256(0x0000000000000000000000000000000400000000000000000000000000000000)) != 0) { + r = + (r * int256(0x0000000000000000000000000000000002582ab704279e8efd15e0265855c47a)) / + int256(0x0000000000000000000000000000001b4c902e273a58678d6d3bfdb93db96d02); // * e ^ -8 + } + // e ^ -4 + if ((x & int256(0x0000000000000000000000000000000200000000000000000000000000000000)) != 0) { + r = + (r * int256(0x000000000000000000000000000000001152aaa3bf81cb9fdb76eae12d029571)) / + int256(0x00000000000000000000000000000003b1cc971a9bb5b9867477440d6d157750); // * e ^ -4 + } + // e ^ -2 + if ((x & int256(0x0000000000000000000000000000000100000000000000000000000000000000)) != 0) { + r = + (r * int256(0x000000000000000000000000000000002f16ac6c59de6f8d5d6f63c1482a7c86)) / + int256(0x000000000000000000000000000000015bf0a8b1457695355fb8ac404e7a79e3); // * e ^ -2 + } + // e ^ -1 + if ((x & int256(0x0000000000000000000000000000000080000000000000000000000000000000)) != 0) { + r = + (r * int256(0x000000000000000000000000000000004da2cbf1be5827f9eb3ad1aa9866ebb3)) / + int256(0x00000000000000000000000000000000d3094c70f034de4b96ff7d5b6f99fcd8); // * e ^ -1 + } + // e ^ -0.5 + if ((x & int256(0x0000000000000000000000000000000040000000000000000000000000000000)) != 0) { + r = + (r * int256(0x0000000000000000000000000000000063afbe7ab2082ba1a0ae5e4eb1b479dc)) / + int256(0x00000000000000000000000000000000a45af1e1f40c333b3de1db4dd55f29a7); // * e ^ -0.5 + } + // e ^ -0.25 + if ((x & int256(0x0000000000000000000000000000000020000000000000000000000000000000)) != 0) { + r = + (r * int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) / + int256(0x00000000000000000000000000000000910b022db7ae67ce76b441c27035c6a1); // * e ^ -0.25 + } + // e ^ -0.125 + if ((x & int256(0x0000000000000000000000000000000010000000000000000000000000000000)) != 0) { + r = + (r * int256(0x00000000000000000000000000000000783eafef1c0a8f3978c7f81824d62ebf)) / + int256(0x0000000000000000000000000000000088415abbe9a76bead8d00cf112e4d4a8); // * e ^ -0.125 + } + } + + /// @dev Returns the multiplication two numbers, reverting on overflow. + function _mul(int256 a, int256 b) private pure returns (int256 c) { + if (a == 0 || b == 0) { + return 0; + } + unchecked { + c = a * b; + if (c / a != b || c / b != a) { + revert("overflow"); + } + } + } + + /// @dev Returns the division of two numbers, reverting on division by zero. + function _div(int256 a, int256 b) private pure returns (int256 c) { + if (b == 0) { + revert("overflow"); + } + if (a == MIN_FIXED_VAL && b == -1) { + revert("overflow"); + } + unchecked { + c = a / b; + } + } + + /// @dev Adds two numbers, reverting on overflow. + function _add(int256 a, int256 b) private pure returns (int256 c) { + unchecked { + c = a + b; + if ((a < 0 && b < 0 && c > a) || (a > 0 && b > 0 && c < a)) { + revert("overflow"); + } + } + } +} diff --git a/packages/horizon/contracts/utils/MathUtils.sol b/packages/horizon/contracts/utils/MathUtils.sol new file mode 100644 index 000000000..3df620b12 --- /dev/null +++ b/packages/horizon/contracts/utils/MathUtils.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +/** + * @title MathUtils Library + * @notice A collection of functions to perform math operations + */ +library MathUtils { + /** + * @dev Calculates the weighted average of two values pondering each of these + * values based on configured weights. The contribution of each value N is + * weightN/(weightA + weightB). The calculation rounds up to ensure the result + * is always greater than the smallest of the two values. + * @param valueA The amount for value A + * @param weightA The weight to use for value A + * @param valueB The amount for value B + * @param weightB The weight to use for value B + */ + function weightedAverageRoundingUp( + uint256 valueA, + uint256 weightA, + uint256 valueB, + uint256 weightB + ) internal pure returns (uint256) { + return ((valueA * weightA) + (valueB * weightB) + (weightA + weightB - 1)) / (weightA + weightB); + } + + /** + * @dev Returns the minimum of two numbers. + */ + function min(uint256 x, uint256 y) internal pure returns (uint256) { + return x <= y ? x : y; + } + + /** + * @dev Returns the difference between two numbers or zero if negative. + */ + function diffOrZero(uint256 x, uint256 y) internal pure returns (uint256) { + return (x > y) ? x - y : 0; + } +} diff --git a/packages/horizon/contracts/utils/TokenUtils.sol b/packages/horizon/contracts/utils/TokenUtils.sol new file mode 100644 index 000000000..7bfc7203c --- /dev/null +++ b/packages/horizon/contracts/utils/TokenUtils.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IGraphToken } from "../IGraphToken.sol"; + +/** + * @title TokenUtils library + * @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. + * @param _graphToken Token to transfer + * @param _from Address sending the tokens + * @param _amount Amount of tokens to transfer + */ + function pullTokens(IGraphToken _graphToken, address _from, uint256 _amount) internal { + if (_amount > 0) { + require(_graphToken.transferFrom(_from, address(this), _amount), "!transfer"); + } + } + + /** + * @dev 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 + */ + function pushTokens(IGraphToken _graphToken, address _to, uint256 _amount) internal { + if (_amount > 0) { + require(_graphToken.transfer(_to, _amount), "!transfer"); + } + } + + /** + * @dev Burn tokens held by this contract. + * @param _graphToken Token to burn + * @param _amount Amount of tokens to burn + */ + function burnTokens(IGraphToken _graphToken, uint256 _amount) internal { + if (_amount > 0) { + _graphToken.burn(_amount); + } + } +} diff --git a/packages/horizon/foundry.toml b/packages/horizon/foundry.toml index 55f7ffd31..38d41a40d 100644 --- a/packages/horizon/foundry.toml +++ b/packages/horizon/foundry.toml @@ -3,4 +3,6 @@ src = 'contracts' out = 'build' libs = ['node_modules', 'lib'] test = 'test' -cache_path = 'cache_forge' \ No newline at end of file +cache_path = 'cache_forge' +optimizer = true +optimizer-runs = 200 diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index f5c9172a8..123791c44 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -3,7 +3,15 @@ import '@nomicfoundation/hardhat-toolbox' import { HardhatUserConfig } from 'hardhat/config' const config: HardhatUserConfig = { - solidity: '0.8.24', + solidity: { + version: '0.8.24', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, paths: { artifacts: './build/contracts', sources: './contracts', diff --git a/packages/horizon/package.json b/packages/horizon/package.json index ec23f62cb..fff88b6d4 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -10,7 +10,7 @@ "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", "build": "forge build && hardhat compile", - "test": "forge test && hardhat test" + "test": "forge test -vvv && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", @@ -20,6 +20,7 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.0", "@nomicfoundation/hardhat-toolbox": "^4.0.0", "@nomicfoundation/hardhat-verify": "^2.0.0", + "@openzeppelin/contracts": "^5.0.2", "@typechain/ethers-v6": "^0.5.0", "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", diff --git a/packages/horizon/remappings.txt b/packages/horizon/remappings.txt index 1bd6482cd..758c61447 100644 --- a/packages/horizon/remappings.txt +++ b/packages/horizon/remappings.txt @@ -3,3 +3,4 @@ forge-std/=lib/forge-std/src/ ds-test/=lib/forge-std/lib/ds-test/src/ eth-gas-reporter/=node_modules/eth-gas-reporter/ hardhat/=node_modules/hardhat/ +@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ diff --git a/packages/horizon/test/HorizonStaking.t.sol b/packages/horizon/test/HorizonStaking.t.sol new file mode 100644 index 000000000..144b0c7a5 --- /dev/null +++ b/packages/horizon/test/HorizonStaking.t.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.24; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; +import { HorizonStaking } from "../contracts/HorizonStaking.sol"; +import { ControllerMock } from "../contracts/mocks/ControllerMock.sol"; +import { HorizonStakingExtension } from "../contracts/HorizonStakingExtension.sol"; +import { ExponentialRebates } from "../contracts/utils/ExponentialRebates.sol"; +import { IHorizonStaking } from "../contracts/IHorizonStaking.sol"; + +contract HorizonStakingTest is Test { + ExponentialRebates rebates; + HorizonStakingExtension ext; + IHorizonStaking staking; + ControllerMock controller; + + function setUp() public { + console.log("Deploying Controller mock"); + controller = new ControllerMock(address(0x1)); + console.log("Deploying HorizonStaking"); + rebates = new ExponentialRebates(); + ext = new HorizonStakingExtension(address(controller), address(0x1), address(rebates)); + staking = IHorizonStaking(address(new HorizonStaking(address(controller), address(ext), address(0x1)))); + } + + function test_SetGlobalOperator() public { + address operator = address(0x1337); + address dataService = address(0x1338); + address serviceProvider = address(this); + + staking.setOperator(operator, dataService, true); + assertTrue(staking.isAuthorized(operator, serviceProvider, dataService)); + } +} diff --git a/packages/horizon/test/HorizonStaking.ts b/packages/horizon/test/HorizonStaking.ts new file mode 100644 index 000000000..6f6e1ad88 --- /dev/null +++ b/packages/horizon/test/HorizonStaking.ts @@ -0,0 +1,38 @@ +import hardhat from 'hardhat' + +import { expect } from 'chai' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { ZeroAddress } from 'ethers' +import { IHorizonStaking } from '../typechain-types' + +const ethers = hardhat.ethers + +describe('HorizonStaking', function () { + async function deployFixture() { + const [owner] = await ethers.getSigners() + const ControllerMock = await ethers.getContractFactory('ControllerMock') + const controller = await ControllerMock.deploy(owner.address) + await controller.waitForDeployment() + const ExponentialRebates = await ethers.getContractFactory('ExponentialRebates') + const exponentialRebates = await ExponentialRebates.deploy() + await exponentialRebates.waitForDeployment() + const HorizonStakingExtension = await ethers.getContractFactory('HorizonStakingExtension') + const horizonStakingExtension = await HorizonStakingExtension.deploy(controller.target, ZeroAddress, exponentialRebates.target) + await horizonStakingExtension.waitForDeployment() + const HorizonStaking = await ethers.getContractFactory('HorizonStaking') + const horizonStakingContract = await HorizonStaking.deploy(controller.target, horizonStakingExtension.target, ZeroAddress) + await horizonStakingContract.waitForDeployment() + const horizonStaking = (await ethers.getContractAt('IHorizonStaking', horizonStakingContract.target)) as unknown as IHorizonStaking + return { horizonStaking, owner } + } + + describe('setOperator', function () { + it('adds an operator', async function () { + const { horizonStaking, owner } = await loadFixture(deployFixture) + const verifier = ethers.Wallet.createRandom().address + const operator = ethers.Wallet.createRandom().address + await horizonStaking.connect(owner).setOperator(operator, verifier, true) + expect(await horizonStaking.isAuthorized(operator, owner, verifier)).to.be.true + }) + }) +}) diff --git a/packages/horizon/test/SimpleTest.t.sol b/packages/horizon/test/SimpleTest.t.sol deleted file mode 100644 index b130e5d34..000000000 --- a/packages/horizon/test/SimpleTest.t.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.10; - -import "forge-std/Test.sol"; -import { SimpleTest } from "../contracts/SimpleTest.sol"; - -contract ContractTest is Test { - SimpleTest simpleTest; - - function setUp() public { - simpleTest = new SimpleTest(); - } - - function test_NumberIs42() public { - assertEq(simpleTest.test(), 42); - } -} diff --git a/packages/horizon/test/SimpleTest.ts b/packages/horizon/test/SimpleTest.ts deleted file mode 100644 index cfcfb1443..000000000 --- a/packages/horizon/test/SimpleTest.ts +++ /dev/null @@ -1,23 +0,0 @@ -import hardhat from 'hardhat' - -import { expect } from 'chai' -import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' - -const ethers = hardhat.ethers - -describe('SimpleTest', function () { - async function deployFixture() { - const [owner] = await ethers.getSigners() - const SimpleTest = await ethers.getContractFactory('SimpleTest') - const simpleTest = await SimpleTest.deploy() - return { simpleTest, owner } - } - - describe('Deployment', function () { - it('Should return 42', async function () { - const { simpleTest } = await loadFixture(deployFixture) - - expect(await simpleTest.test()).to.equal(42) - }) - }) -}) diff --git a/yarn.lock b/yarn.lock index 27dfd84b0..00e728326 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2935,6 +2935,7 @@ __metadata: "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0" "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" "@nomicfoundation/hardhat-verify": "npm:^2.0.0" + "@openzeppelin/contracts": "npm:^5.0.2" "@typechain/ethers-v6": "npm:^0.5.0" "@typechain/hardhat": "npm:^9.0.0" "@types/chai": "npm:^4.2.0" @@ -5044,6 +5045,13 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts@npm:^5.0.2": + version: 5.0.2 + resolution: "@openzeppelin/contracts@npm:5.0.2" + checksum: d042661db7bb2f3a4b9ef30bba332e86ac20907d171f2ebfccdc9255cc69b62786fead8d6904b8148a8f26946bc7c15eead91b95f75db0c193a99d52e528663e + languageName: node + linkType: hard + "@openzeppelin/defender-admin-client@npm:^1.46.0": version: 1.54.1 resolution: "@openzeppelin/defender-admin-client@npm:1.54.1" From 46e5da536288ff30edfcac961e597cc3ba2fd6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 17 May 2024 17:55:11 -0300 Subject: [PATCH 020/277] [WIP] Horizon: add subgraph data service (#946) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: add first draft IHorizonStaking * fix: horizon staking interface compilation errors Signed-off-by: Tomás Migone * chore: bump contracts package version Signed-off-by: Tomás Migone * fix(contracts): build type code Signed-off-by: Tomás Migone * feat: add subgraph service boilerplate Signed-off-by: Tomás Migone * chore: add subgraph service contracts boilerplate Signed-off-by: Tomás Migone * feat(ss): add register flow Signed-off-by: Tomás Migone * feat(ss): add slash flow Signed-off-by: Tomás Migone * wip: redeem flow Signed-off-by: Tomás Migone * feat: query fee redeem flow Signed-off-by: Tomás Migone * fix: add events to subgraph service redeem flow Signed-off-by: Tomás Migone * feat: start allocation flows Signed-off-by: Tomás Migone * chore(horizon): add horizon package boilerplate Signed-off-by: Tomás Migone * chore: horizon dispute manager WIP * chore: testing * chore: rename DisputeManager to SubgraphDisputeManager * fix: remove unneeded code * fix: merge conflicts * fix: indentation * chore: add Ownable * chore: use errors * chore: use subgraph service contract for dispute tests * fix: remove unused code * feat: start work on data service sdk Signed-off-by: Tomás Migone * feat(data-service): break out fee model from subgraph service Signed-off-by: Tomás Migone * chore: simplify data service sdk naming convention Signed-off-by: Tomás Migone * chore(ss): simplify naming convention Signed-off-by: Tomás Migone * fix: cleanup Signed-off-by: Tomás Migone * feat(subgraph-service): register via ds sdk Signed-off-by: Tomás Migone * feat(data-service): add ownable and rescuable data service extensions Signed-off-by: Tomás Migone * feat: provision tracker Signed-off-by: Tomás Migone * feat: add stop service to subgraph service Signed-off-by: Tomás Migone * chore: minor tweaks to ss Signed-off-by: Tomás Migone * chore: update start stop service in ss Signed-off-by: Tomás Migone * feat: improvements to data service framework Signed-off-by: Tomás Migone * feat(ss): dont delete allos when closing, update getallocation Signed-off-by: Tomás Migone * fix: final touches to service flows on subgraph service Signed-off-by: Tomás Migone * chore(ss): rewrite using allocation library Signed-off-by: Tomás Migone * chore(ds): rewrite data service using provision handler and getter Signed-off-by: Tomás Migone * chore(ss): refactor with allocation manager Signed-off-by: Tomás Migone * chore: provide not implemented default fns for data service base contract Signed-off-by: Tomás Migone * feat(ss): revamp allocations, add legacy allocations and migrations Signed-off-by: Tomás Migone * feat(ds): add pausable data service extension Signed-off-by: Tomás Migone * fix(ds): add rescuer role to DataServiceRescuable, dont use Ownable Signed-off-by: Tomás Migone * chore(ds): move PPM lib to data service sdk Signed-off-by: Tomás Migone * chore(ds): rename ProvisionHandler to ProvisionManager Signed-off-by: Tomás Migone * chore: clean up inheritance and interfacesd Signed-off-by: Tomás Migone * chore: cleanup dependencies Signed-off-by: Tomás Migone * chore: ensure consistent stlye in sol files Signed-off-by: Tomás Migone * chore(ss): use math ppm for dispute manager Signed-off-by: Tomás Migone * chore: use attestation lib for dispute manager Signed-off-by: Tomás Migone * chore: attestation manager Signed-off-by: Tomás Migone * chore: remove unused event Signed-off-by: Tomás Migone * chore: readd event in proper contract Signed-off-by: Tomás Migone * docs: add natspec to data service contract Signed-off-by: Tomás Migone * feat: implement curation fees distribution Signed-off-by: Tomás Migone * chore(solhint): update lint rules Signed-off-by: Tomás Migone * chore: apply new linting rules Signed-off-by: Tomás Migone * fix: stack too deep error in subgraph service collect Signed-off-by: Tomás Migone * feat(solhint): add custom leading underscore rule Signed-off-by: Tomás Migone * feat(solhint): fix leading underscore errors with plugin Signed-off-by: Tomás Migone * fix(solhint): properly lint function parameters Signed-off-by: Tomás Migone * chore: apply latest linting rules Signed-off-by: Tomás Migone * docs: natspec for data service interface Signed-off-by: Tomás Migone * chore: fix linting Signed-off-by: Tomás Migone * fix: horizon dispute manager tests * fix: yarn lock Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone Co-authored-by: Pablo Carranza Velez Co-authored-by: Miguel de Elias Co-authored-by: Maikol <86025070+Maikol@users.noreply.github.com> --- .github/workflows/ci-subgraph-service.yml | 30 + .gitmodules | 3 + .husky/pre-commit | 5 + README.md | 1 + package.json | 1 + .../contracts/governance/Controller.sol | 2 +- .../contracts/governance/Governed.sol | 2 +- .../contracts/governance/Pausable.sol | 2 +- .../contracts/staking/IHorizonStaking.sol | 166 ++ .../contracts/contracts/token/IGraphToken.sol | 2 +- .../contracts/contracts/utils/TokenUtils.sol | 2 +- packages/horizon/contracts/SimpleTest.sol | 10 + packages/horizon/test/SimpleTest.t.sol | 17 + packages/horizon/test/SimpleTest.ts | 23 + packages/solhint-graph-config/README.md | 7 + packages/solhint-graph-config/index.js | 24 +- packages/solhint-graph-config/package.json | 5 +- packages/solhint-graph-config/plugin/index.js | 114 + .../solhint-graph-config/plugin/package.json | 5 + packages/subgraph-service/README.md | 13 + .../contracts/DisputeManager.sol | 783 +++++ .../contracts/DisputeManagerStorage.sol | 33 + .../contracts/SubgraphService.sol | 273 ++ .../contracts/SubgraphServiceStorage.sol | 19 + .../contracts/TAPVerifier.sol | 220 ++ .../contracts/data-service/DataService.sol | 39 + .../data-service/DataServiceStorage.sol | 7 + .../contracts/data-service/GraphDirectory.sol | 55 + .../contracts/data-service/IDataService.sol | 164 ++ .../extensions/DataServiceFees.sol | 99 + .../extensions/DataServiceFeesStorage.sol | 20 + .../extensions/DataServicePausable.sol | 35 + .../extensions/DataServiceRescuable.sol | 64 + .../extensions/IDataServiceFees.sol | 27 + .../extensions/IDataServicePausable.sol | 9 + .../extensions/IDataServiceRescuable.sol | 9 + .../data-service/libraries/Denominations.sol | 15 + .../data-service/libraries/PPMMath.sol | 32 + .../libraries/ProvisionGetter.sol | 21 + .../libraries/ProvisionTracker.sol | 43 + .../data-service/libraries/UintRange.sol | 10 + .../utilities/ProvisionManager.sol | 109 + .../utilities/ProvisionManagerStorage.sol | 25 + .../contracts/interfaces/IDisputeManager.sol | 86 + .../contracts/interfaces/IGraphEscrow.sol | 6 + .../contracts/interfaces/IGraphPayments.sol | 17 + .../contracts/interfaces/ISubgraphService.sol | 32 + .../contracts/interfaces/ITAPVerifier.sol | 24 + .../contracts/libraries/Allocation.sol | 101 + .../contracts/libraries/Attestation.sol | 115 + .../contracts/libraries/LegacyAllocation.sol | 46 + .../contracts/utilities/AllocationManager.sol | 251 ++ .../utilities/AllocationManagerStorage.sol | 24 + .../utilities/AttestationManager.sol | 77 + .../utilities/AttestationManagerStorage.sol | 9 + .../contracts/utilities/Directory.sol | 38 + packages/subgraph-service/eslint.config.js | 21 + packages/subgraph-service/foundry.toml | 6 + packages/subgraph-service/hardhat.config.ts | 37 + packages/subgraph-service/lib/forge-std | 1 + packages/subgraph-service/package.json | 63 + packages/subgraph-service/prettier.config.js | 2 + packages/subgraph-service/remappings.txt | 5 + packages/subgraph-service/scripts/deploy.ts | 28 + .../test/DisputeManager.t.sol | 501 ++++ .../test/mocks/MockGRTToken.sol | 46 + .../test/mocks/MockHorizonStaking.sol | 108 + .../test/mocks/MockRewardsManager.sol | 50 + packages/subgraph-service/tsconfig.json | 18 + yarn.lock | 2603 +++++++---------- 70 files changed, 5358 insertions(+), 1502 deletions(-) create mode 100644 .github/workflows/ci-subgraph-service.yml create mode 100644 packages/contracts/contracts/staking/IHorizonStaking.sol create mode 100644 packages/horizon/contracts/SimpleTest.sol create mode 100644 packages/horizon/test/SimpleTest.t.sol create mode 100644 packages/horizon/test/SimpleTest.ts create mode 100644 packages/solhint-graph-config/plugin/index.js create mode 100644 packages/solhint-graph-config/plugin/package.json create mode 100644 packages/subgraph-service/README.md create mode 100644 packages/subgraph-service/contracts/DisputeManager.sol create mode 100644 packages/subgraph-service/contracts/DisputeManagerStorage.sol create mode 100644 packages/subgraph-service/contracts/SubgraphService.sol create mode 100644 packages/subgraph-service/contracts/SubgraphServiceStorage.sol create mode 100644 packages/subgraph-service/contracts/TAPVerifier.sol create mode 100644 packages/subgraph-service/contracts/data-service/DataService.sol create mode 100644 packages/subgraph-service/contracts/data-service/DataServiceStorage.sol create mode 100644 packages/subgraph-service/contracts/data-service/GraphDirectory.sol create mode 100644 packages/subgraph-service/contracts/data-service/IDataService.sol create mode 100644 packages/subgraph-service/contracts/data-service/extensions/DataServiceFees.sol create mode 100644 packages/subgraph-service/contracts/data-service/extensions/DataServiceFeesStorage.sol create mode 100644 packages/subgraph-service/contracts/data-service/extensions/DataServicePausable.sol create mode 100644 packages/subgraph-service/contracts/data-service/extensions/DataServiceRescuable.sol create mode 100644 packages/subgraph-service/contracts/data-service/extensions/IDataServiceFees.sol create mode 100644 packages/subgraph-service/contracts/data-service/extensions/IDataServicePausable.sol create mode 100644 packages/subgraph-service/contracts/data-service/extensions/IDataServiceRescuable.sol create mode 100644 packages/subgraph-service/contracts/data-service/libraries/Denominations.sol create mode 100644 packages/subgraph-service/contracts/data-service/libraries/PPMMath.sol create mode 100644 packages/subgraph-service/contracts/data-service/libraries/ProvisionGetter.sol create mode 100644 packages/subgraph-service/contracts/data-service/libraries/ProvisionTracker.sol create mode 100644 packages/subgraph-service/contracts/data-service/libraries/UintRange.sol create mode 100644 packages/subgraph-service/contracts/data-service/utilities/ProvisionManager.sol create mode 100644 packages/subgraph-service/contracts/data-service/utilities/ProvisionManagerStorage.sol create mode 100644 packages/subgraph-service/contracts/interfaces/IDisputeManager.sol create mode 100644 packages/subgraph-service/contracts/interfaces/IGraphEscrow.sol create mode 100644 packages/subgraph-service/contracts/interfaces/IGraphPayments.sol create mode 100644 packages/subgraph-service/contracts/interfaces/ISubgraphService.sol create mode 100644 packages/subgraph-service/contracts/interfaces/ITAPVerifier.sol create mode 100644 packages/subgraph-service/contracts/libraries/Allocation.sol create mode 100644 packages/subgraph-service/contracts/libraries/Attestation.sol create mode 100644 packages/subgraph-service/contracts/libraries/LegacyAllocation.sol create mode 100644 packages/subgraph-service/contracts/utilities/AllocationManager.sol create mode 100644 packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol create mode 100644 packages/subgraph-service/contracts/utilities/AttestationManager.sol create mode 100644 packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol create mode 100644 packages/subgraph-service/contracts/utilities/Directory.sol create mode 100644 packages/subgraph-service/eslint.config.js create mode 100644 packages/subgraph-service/foundry.toml create mode 100644 packages/subgraph-service/hardhat.config.ts create mode 160000 packages/subgraph-service/lib/forge-std create mode 100644 packages/subgraph-service/package.json create mode 100644 packages/subgraph-service/prettier.config.js create mode 100644 packages/subgraph-service/remappings.txt create mode 100644 packages/subgraph-service/scripts/deploy.ts create mode 100644 packages/subgraph-service/test/DisputeManager.t.sol create mode 100644 packages/subgraph-service/test/mocks/MockGRTToken.sol create mode 100644 packages/subgraph-service/test/mocks/MockHorizonStaking.sol create mode 100644 packages/subgraph-service/test/mocks/MockRewardsManager.sol create mode 100644 packages/subgraph-service/tsconfig.json diff --git a/.github/workflows/ci-subgraph-service.yml b/.github/workflows/ci-subgraph-service.yml new file mode 100644 index 000000000..bda15deff --- /dev/null +++ b/.github/workflows/ci-subgraph-service.yml @@ -0,0 +1,30 @@ +name: CI - packages/subgraph-service + +env: + CI: true + +on: + push: + branches: "*" + paths: + - packages/subgraph-service/** + pull_request: + branches: "*" + paths: + - packages/subgraph-service/** + workflow_dispatch: + +jobs: + test-ci: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set up environment + uses: ./.github/actions/setup + - name: Run tests + run: | + pushd packages/subgraph-service + yarn test \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index edd86d2b7..6e4ecf4c6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +[submodule "packages/subgraph-service/lib/forge-std"] + path = packages/subgraph-service/lib/forge-std + url = https://github.com/foundry-rs/forge-std [submodule "packages/horizon/lib/forge-std"] path = packages/horizon/lib/forge-std url = https://github.com/foundry-rs/forge-std diff --git a/.husky/pre-commit b/.husky/pre-commit index 92fa26604..aa9adeab4 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -6,6 +6,11 @@ pushd packages/contracts npx --no-install lint-staged popd +# subgraph service +pushd packages/subgraph-service +npx --no-install lint-staged +popd + # data-edge pushd packages/data-edge npx --no-install lint-staged diff --git a/README.md b/README.md index a36de65bf..d9b46bb52 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ This repository is a Yarn workspaces monorepo containing the following packages: | [horizon](./packages/horizon) | [![npm version]()]() | Contracts for Graph Horizon, the next iteration of The Graph protocol. | | [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 | | [solhint-graph-config](./packages/eslint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for Solidity projects. | +| [subgraph-service](./packages/subgraph-service) | [![npm version]()]() | Contracts for the Subgraph data service in Graph Horizon. | | [token-distribution](./packages/token-distribution) | - | Contracts managing token locks for network participants | diff --git a/package.json b/package.json index d27a50288..126006c96 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "packages/horizon", "packages/sdk", "packages/solhint-graph-config", + "packages/subgraph-service", "packages/token-distribution" ], "scripts": { diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index affb29a05..74854cbfe 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.7.6 <0.9.0; import { IController } from "./IController.sol"; import { IManaged } from "./IManaged.sol"; diff --git a/packages/contracts/contracts/governance/Governed.sol b/packages/contracts/contracts/governance/Governed.sol index f692b2d19..570e2839c 100644 --- a/packages/contracts/contracts/governance/Governed.sol +++ b/packages/contracts/contracts/governance/Governed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.7.6 <0.9.0; /** * @title Graph Governance contract diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 552b0aa15..1e9baf5fe 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.7.6 <0.9.0; abstract contract Pausable { /** diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol new file mode 100644 index 000000000..b45aee1ac --- /dev/null +++ b/packages/contracts/contracts/staking/IHorizonStaking.sol @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.7.6 <0.9.0; +pragma abicoder v2; + +interface Test { + function test() external returns (uint256); +} + +interface IHorizonStaking { + struct Provision { + // Service provider that created the provision + address serviceProvider; + // tokens in the provision + uint256 tokens; + // delegated tokens in the provision + uint256 delegatedTokens; + // tokens that are being thawed (and will stop being slashable soon) + uint256 tokensThawing; + // timestamp of provision creation + uint64 createdAt; + // authority to slash the provision + address verifier; + // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed + uint32 maxVerifierCut; + // time, in seconds, tokens must thaw before being withdrawn + uint64 thawingPeriod; + } + + // the new "Indexer" struct + struct ServiceProviderInternal { + // Tokens on the Service Provider stake (staked by the provider) + uint256 tokensStaked; + // Tokens used in allocations + uint256 __DEPRECATED_tokensAllocated; + // Tokens locked for withdrawal subject to thawing period + uint256 __DEPRECATED_tokensLocked; + // Block when locked tokens can be withdrawn + uint256 __DEPRECATED_tokensLockedUntil; + // tokens used in a provision + uint256 tokensProvisioned; + // tokens that initiated a thawing in any one of the provider's provisions + uint256 tokensRequestedThaw; + // tokens that have been removed from any one of the provider's provisions after thawing + uint256 tokensFulfilledThaw; + // provisions that take priority for undelegation force thawing + bytes32[] forceThawProvisions; + } + + struct ServiceProvider { + // Tokens on the provider stake (staked by the provider) + uint256 tokensStaked; + // tokens used in a provision + uint256 tokensProvisioned; + // tokens that initiated a thawing in any one of the provider's provisions + uint256 tokensRequestedThaw; + // tokens that have been removed from any one of the provider's provisions after thawing + uint256 tokensFulfilledThaw; + // provisions that take priority for undelegation force thawing + bytes32[] forceThawProvisions; + } + + struct DelegationPool { + uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase + uint32 __DEPRECATED_indexingRewardCut; // in PPM + uint32 __DEPRECATED_queryFeeCut; // in PPM + uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated + uint256 tokens; // Total tokens as pool reserves + uint256 shares; // Total shares minted in the pool + mapping(address => Delegation) delegators; // Mapping of delegator => Delegation + } + + struct Delegation { + // shares owned by the delegator in the pool + uint256 shares; + // tokens delegated to the pool + uint256 tokens; + // Timestamp when locked tokens can be undelegated (after the timelock) + uint256 tokensLockedUntil; + } + + struct ThawRequest { + // tokens that are being thawed by this request + uint256 tokens; + // the provision id to which this request corresponds to + bytes32 provisionId; + // the address that initiated the thaw request, allowed to remove the funds once thawed + address owner; + // the timestamp when the thawed funds can be removed from the provision + uint64 thawingUntil; + // the value of `ServiceProvider.tokensRequestedThaw` the moment the thaw request is created + uint256 tokensRequestedThawSnapshot; + } + + // whitelist/deny a verifier + function allowVerifier(address verifier, bool allow) external; + + // deposit stake + function stake(uint256 tokens) external; + + // create a provision + function provision(uint256 tokens, address verifier, uint32 maxVerifierCut, uint64 thawingPeriod) external; + + // accept a provision + function acceptProvision(address serviceProvider) external; + + // initiate a thawing to remove tokens from a provision + function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId); + + // moves thawed stake from a provision back into the provider's available stake + function deprovision(bytes32 thawRequestId) external; + + // moves thawed stake from one provision into another provision + function reprovision(bytes32 thawRequestId, bytes32 provisionId) external; + + // moves thawed stake back to the owner's account - stake is removed from the protocol + function withdraw(bytes32 thawRequestId) external; + + // delegate tokens to a provider + function delegate(address serviceProvider, uint256 tokens) external; + + // undelegate tokens + function undelegate( + address serviceProvider, + uint256 tokens, + bytes32[] calldata provisions + ) external returns (bytes32 thawRequestId); + + // slash a service provider + function slash(address serviceProvider, uint256 tokens, uint256 reward, address rewardsDestination) external; + + // set the Service Provider's preferred provisions to be force thawed + function setForceThawProvisions(bytes32[] calldata provisions) external; + + // total staked tokens to the provider + // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` + function getStake(address serviceProvider) external view returns (uint256 tokens); + + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address serviceProvider) external view returns (uint256 tokens); + + // staked tokens the provider can provision before hitting the delegation cap + // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` + function getCapacity(address serviceProvider) external view returns (uint256 tokens); + + // provisioned tokens that are not being used + // `Provision.tokens - Provision.tokensThawing` + function getTokensAvailable(address serviceProvider, address verifier) external view returns (uint256 tokens); + + function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); + + function getProvision(address serviceProvider, address verifier) external view returns (Provision memory); + + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param _operator The address to check for auth + * @param _serviceProvider The service provider on behalf of whom they're claiming to act + * @param _verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized(address _operator, address _serviceProvider, address _verifier) external view returns (bool); + + function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256 delegationCut); + function addToDelegationPool(address serviceProvider, uint256 tokens) external; + function stakeToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external; +} diff --git a/packages/contracts/contracts/token/IGraphToken.sol b/packages/contracts/contracts/token/IGraphToken.sol index 8255e18d5..f24467d42 100644 --- a/packages/contracts/contracts/token/IGraphToken.sol +++ b/packages/contracts/contracts/token/IGraphToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.7.6 <=0.9.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/packages/contracts/contracts/utils/TokenUtils.sol b/packages/contracts/contracts/utils/TokenUtils.sol index 265f918a5..09d9ed704 100644 --- a/packages/contracts/contracts/utils/TokenUtils.sol +++ b/packages/contracts/contracts/utils/TokenUtils.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.7.6 <=0.8.24; import "../token/IGraphToken.sol"; diff --git a/packages/horizon/contracts/SimpleTest.sol b/packages/horizon/contracts/SimpleTest.sol new file mode 100644 index 000000000..5cc28d9cc --- /dev/null +++ b/packages/horizon/contracts/SimpleTest.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.4.0 <0.9.0; + +import { Test } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; + +contract SimpleTest is Test { + function test() external pure returns (uint256) { + return 42; + } +} diff --git a/packages/horizon/test/SimpleTest.t.sol b/packages/horizon/test/SimpleTest.t.sol new file mode 100644 index 000000000..b130e5d34 --- /dev/null +++ b/packages/horizon/test/SimpleTest.t.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.10; + +import "forge-std/Test.sol"; +import { SimpleTest } from "../contracts/SimpleTest.sol"; + +contract ContractTest is Test { + SimpleTest simpleTest; + + function setUp() public { + simpleTest = new SimpleTest(); + } + + function test_NumberIs42() public { + assertEq(simpleTest.test(), 42); + } +} diff --git a/packages/horizon/test/SimpleTest.ts b/packages/horizon/test/SimpleTest.ts new file mode 100644 index 000000000..cfcfb1443 --- /dev/null +++ b/packages/horizon/test/SimpleTest.ts @@ -0,0 +1,23 @@ +import hardhat from 'hardhat' + +import { expect } from 'chai' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' + +const ethers = hardhat.ethers + +describe('SimpleTest', function () { + async function deployFixture() { + const [owner] = await ethers.getSigners() + const SimpleTest = await ethers.getContractFactory('SimpleTest') + const simpleTest = await SimpleTest.deploy() + return { simpleTest, owner } + } + + describe('Deployment', function () { + it('Should return 42', async function () { + const { simpleTest } = await loadFixture(deployFixture) + + expect(await simpleTest.test()).to.equal(42) + }) + }) +}) diff --git a/packages/solhint-graph-config/README.md b/packages/solhint-graph-config/README.md index 7a724946b..4257b2dd8 100644 --- a/packages/solhint-graph-config/README.md +++ b/packages/solhint-graph-config/README.md @@ -17,6 +17,13 @@ yarn add --dev solhint solhint-graph-config yarn add --dev solhint solhint-graph-config@workspace:^x.y.z ``` +To use graph plugin you'll also need to manually add the plugin to your `package.json`: +```json + "devDependencies": { + "solhint-plugin-graph": "file:node_modules/solhint-graph-config/plugin" + } +``` + ### Configuration Run `solhint` with `node_modules/solhint-graph-config/index.js` as the configuration file. We suggest creating an npm script to make it easier to run: diff --git a/packages/solhint-graph-config/index.js b/packages/solhint-graph-config/index.js index b37be2810..f7193d748 100644 --- a/packages/solhint-graph-config/index.js +++ b/packages/solhint-graph-config/index.js @@ -1,12 +1,28 @@ module.exports = { + plugins: [ 'graph' ], extends: 'solhint:recommended', rules: { - 'func-visibility': ['warn', { ignoreConstructors: true }], - 'compiler-version': ['off'], + // best practices + 'no-empty-blocks': 'off', 'constructor-syntax': 'warn', + + // style rules + 'private-vars-leading-underscore': 'off', // see graph/leading-underscore + 'const-name-snakecase': 'warn', + 'named-parameters-mapping': 'warn', + 'imports-on-top': 'warn', + 'ordering': 'warn', + 'visibility-modifier-order': 'warn', + + // miscellaneous 'quotes': ['error', 'double'], - 'reason-string': ['off'], + + // security + 'compiler-version': ['off'], + 'func-visibility': ['warn', { ignoreConstructors: true }], 'not-rely-on-time': 'off', - 'no-empty-blocks': 'off', + + // graph + 'graph/leading-underscore': 'warn', }, } diff --git a/packages/solhint-graph-config/package.json b/packages/solhint-graph-config/package.json index 2ead8bbef..d976b3cb9 100644 --- a/packages/solhint-graph-config/package.json +++ b/packages/solhint-graph-config/package.json @@ -5,9 +5,12 @@ "main": "index.js", "author": "The Graph Team", "license": "GPL-2.0-or-later", + "dependencies": { + "solhint-plugin-graph": "file:plugin" + }, "peerDependencies": { "prettier": "^3.2.5", "prettier-plugin-solidity": "^1.3.1", - "solhint": "^4.1.1" + "solhint": "^4.5.4" } } diff --git a/packages/solhint-graph-config/plugin/index.js b/packages/solhint-graph-config/plugin/index.js new file mode 100644 index 000000000..cd16840e8 --- /dev/null +++ b/packages/solhint-graph-config/plugin/index.js @@ -0,0 +1,114 @@ +function hasLeadingUnderscore(text) { + return text && text[0] === '_' +} + +class Base { + constructor(reporter, config, source, fileName) { + this.reporter = reporter; + this.ignored = this.constructor.global; + this.ruleId = this.constructor.ruleId; + if (this.ruleId === undefined) { + throw Error('missing ruleId static property'); + } + } + + error(node, message, fix) { + if (!this.ignored) { + this.reporter.error(node, this.ruleId, message, fix); + } + } +} + +module.exports = [ + class extends Base { + static ruleId = 'leading-underscore'; + + ContractDefinition(node) { + if (node.kind === 'library') { + this.inLibrary = true + } + } + + 'ContractDefinition:exit'() { + this.inLibrary = false + } + + StateVariableDeclaration() { + this.inStateVariableDeclaration = true + } + + 'StateVariableDeclaration:exit'() { + this.inStateVariableDeclaration = false + } + + VariableDeclaration(node) { + if (!this.inLibrary) { + if (!this.inStateVariableDeclaration) { + this.validateName(node, false, 'variable') + return + } + + this.validateName(node, 'variable') + } + + } + + FunctionDefinition(node) { + if (!this.inLibrary) { + if (!node.name) { + return + } + for (const parameter of node.parameters) { + parameter.visibility = node.visibility + } + + this.validateName(node, 'function') + + } + } + + validateName(node, type) { + const isPrivate = node.visibility === 'private' + const isInternal = node.visibility === 'internal' || node.visibility === 'default' + const isConstant = node.isDeclaredConst + const isImmutable = node.isImmutable + const shouldHaveLeadingUnderscore = (isPrivate || isInternal) && !(isConstant || isImmutable) + + if (node.name === null) { + return + } + + if (hasLeadingUnderscore(node.name) !== shouldHaveLeadingUnderscore) { + this._error(node, node.name, shouldHaveLeadingUnderscore, type) + } + } + + fixStatement(node, shouldHaveLeadingUnderscore, type) { + let range + + if (type === 'function') { + range = node.range + range[0] += 8 + } else if (type === 'parameter') { + range = node.identifier.range + } else { + range = node.identifier.range + range[0] -= 1 + } + + return (fixer) => + shouldHaveLeadingUnderscore + ? fixer.insertTextBeforeRange(range, ' _') + : fixer.removeRange([range[0] + 1, range[0] + 1]) + } + + _error(node, name, shouldHaveLeadingUnderscore, type) { + this.error( + node, + `'${name}' ${shouldHaveLeadingUnderscore ? 'should' : 'should not'} start with _`, + this.fixStatement(node, shouldHaveLeadingUnderscore, type) + ) + } + }, + +]; \ No newline at end of file diff --git a/packages/solhint-graph-config/plugin/package.json b/packages/solhint-graph-config/plugin/package.json new file mode 100644 index 000000000..53bab497d --- /dev/null +++ b/packages/solhint-graph-config/plugin/package.json @@ -0,0 +1,5 @@ +{ + "name": "solhint-plugin-graph", + "version": "0.0.0", + "private": true +} \ No newline at end of file diff --git a/packages/subgraph-service/README.md b/packages/subgraph-service/README.md new file mode 100644 index 000000000..7be82e5d6 --- /dev/null +++ b/packages/subgraph-service/README.md @@ -0,0 +1,13 @@ +# Sample Hardhat Project + +This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract. + +Try running some of the following tasks: + +```shell +npx hardhat help +npx hardhat test +REPORT_GAS=true npx hardhat test +npx hardhat node +npx hardhat run scripts/deploy.ts +``` diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol new file mode 100644 index 000000000..dc5f785f2 --- /dev/null +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -0,0 +1,783 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.24; +pragma abicoder v2; + +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; +import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; +import { GraphDirectory } from "./data-service/GraphDirectory.sol"; +import { AttestationManager } from "./utilities/AttestationManager.sol"; + +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; +import { Allocation } from "./libraries/Allocation.sol"; +import { PPMMath } from "./data-service/libraries/PPMMath.sol"; +import { Attestation } from "./libraries/Attestation.sol"; + +/* + * @title DisputeManager + * @notice Provides a way to align the incentives of participants by having slashing as deterrent + * for incorrect behaviour. + * + * There are two types of disputes that can be created: Query disputes and Indexing disputes. + * + * Query Disputes: + * Graph nodes receive queries and return responses with signed receipts called attestations. + * An attestation can be disputed if the consumer thinks the query response was invalid. + * Indexers use the derived private key for an allocation to sign attestations. + * + * Indexing Disputes: + * Indexers present a Proof of Indexing (POI) when they close allocations to prove + * they were indexing a subgraph. The Staking contract emits that proof with the format + * keccak256(indexer.address, POI). + * Any challenger can dispute the validity of a POI by submitting a dispute to this contract + * along with a deposit. + * + * Arbitration: + * Disputes can only be accepted, rejected or drawn by the arbitrator role that can be delegated + * to a EOA or DAO. + */ +contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeManagerV1Storage, IDisputeManager { + using PPMMath for uint256; + + // -- Events -- + event ArbitratorSet(address arbitrator); + event DisputePeriodSet(uint64 disputePeriod); + event MinimumDepositSet(uint256 minimumDeposit); + event MaxSlashingPercentageSet(uint32 maxSlashingPercentage); + event FishermanRewardPercentageSet(uint32 fishermanRewardPercentage); + event SubgraphServiceSet(address indexed subgraphService); + + /** + * @dev 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. + */ + event QueryDisputeCreated( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens, + bytes32 subgraphDeploymentId, + bytes attestation + ); + + /** + * @dev Emitted when an indexing dispute is created for `allocationId` and `indexer` + * by `fisherman`. + * The event emits the amount of `tokens` deposited by the fisherman. + */ + event IndexingDisputeCreated( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens, + address allocationId + ); + + /** + * @dev 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. + */ + event DisputeAccepted( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens + ); + + /** + * @dev Emitted when arbitrator rejects a `disputeId` for `indexer` created by `fisherman`. + * The event emits the amount `tokens` burned from the fisherman deposit. + */ + event DisputeRejected( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens + ); + + /** + * @dev 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. + */ + event DisputeDrawn(bytes32 indexed disputeId, address indexed indexer, address indexed fisherman, uint256 tokens); + + /** + * @dev 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. + */ + event DisputeLinked(bytes32 indexed disputeId1, bytes32 indexed disputeId2); + + // -- Errors -- + + error DisputeManagerNotArbitrator(); + error DisputeManagerNotFisherman(); + error DisputeManagerInvalidZeroAddress(); + error DisputeManagerDisputePeriodZero(); + error DisputeManagerZeroTokens(); + error DisputeManagerInvalidDispute(bytes32 disputeId); + error DisputeManagerInvalidMinimumDeposit(uint256 minimumDeposit); + error DisputeManagerInvalidFishermanReward(uint32 percentage); + error DisputeManagerInvalidMaxSlashingPercentage(uint32 maxSlashingPercentage); + error DisputeManagerInvalidSlashAmount(uint256 slashAmount); + error DisputeManagerInvalidDisputeStatus(IDisputeManager.DisputeStatus status); + error DisputeManagerInsufficientDeposit(uint256 deposit, uint256 minimumDeposit); + error DisputeManagerDisputeAlreadyCreated(bytes32 disputeId); + error DisputeManagerDisputePeriodNotFinished(); + error DisputeManagerMustAcceptRelatedDispute(bytes32 disputeId, bytes32 relatedDisputeId); + error DisputeManagerIndexerNotFound(address allocationId); + error DisputeManagerNonMatchingSubgraphDeployment(bytes32 subgraphDeploymentId1, bytes32 subgraphDeploymentId2); + error DisputeManagerNonConflictingAttestations( + bytes32 requestCID1, + bytes32 responseCID1, + bytes32 subgraphDeploymentId1, + bytes32 requestCID2, + bytes32 responseCID2, + bytes32 subgraphDeploymentId2 + ); + + // -- Modifiers -- + + /** + * @dev Check if the caller is the arbitrator. + */ + modifier onlyArbitrator() { + if (msg.sender != arbitrator) { + revert DisputeManagerNotArbitrator(); + } + _; + } + + modifier onlyPendingDispute(bytes32 disputeId) { + if (!isDisputeCreated(disputeId)) { + revert DisputeManagerInvalidDispute(disputeId); + } + + if (disputes[disputeId].status != IDisputeManager.DisputeStatus.Pending) { + revert DisputeManagerInvalidDisputeStatus(disputes[disputeId].status); + } + _; + } + + modifier onlyFisherman(bytes32 disputeId) { + if (!isDisputeCreated(disputeId)) { + revert DisputeManagerInvalidDispute(disputeId); + } + + if (msg.sender != disputes[disputeId].fisherman) { + revert DisputeManagerNotFisherman(); + } + _; + } + + // -- Functions -- + + /** + * @dev Initialize this contract. + * @param controller Address of Graph Controller contract + * @param arbitrator Arbitrator role + * @param disputePeriod Dispute period in seconds + * @param minimumDeposit Minimum deposit required to create a Dispute + * @param fishermanRewardPercentage Percent of slashed funds for fisherman (ppm) + * @param maxSlashingPercentage Maximum percentage of indexer stake that can be slashed (ppm) + */ + constructor( + address controller, + address arbitrator, + uint64 disputePeriod, + uint256 minimumDeposit, + uint32 fishermanRewardPercentage, + uint32 maxSlashingPercentage + ) Ownable(msg.sender) GraphDirectory(controller) { + // Settings + _setArbitrator(arbitrator); + _setDisputePeriod(disputePeriod); + _setMinimumDeposit(minimumDeposit); + _setFishermanRewardPercentage(fishermanRewardPercentage); + _setMaxSlashingPercentage(maxSlashingPercentage); + } + + /** + * @dev Create an indexing dispute for the arbitrator to resolve. + * 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 + */ + function createIndexingDispute(address allocationId, uint256 deposit) external override returns (bytes32) { + // Get funds from submitter + _pullSubmitterDeposit(deposit); + + // Create a dispute + return _createIndexingDisputeWithAllocation(msg.sender, deposit, allocationId); + } + + /** + * @dev 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 + */ + function createQueryDispute(bytes calldata attestationData, uint256 deposit) external override returns (bytes32) { + // Get funds from submitter + _pullSubmitterDeposit(deposit); + + // Create a dispute + return + _createQueryDisputeWithAttestation( + msg.sender, + deposit, + Attestation.parse(attestationData), + attestationData + ); + } + + /** + * @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 + */ + function createQueryDisputeConflict( + bytes calldata attestationData1, + bytes calldata attestationData2 + ) external override returns (bytes32, bytes32) { + address fisherman = msg.sender; + + // Parse each attestation + Attestation.State memory attestation1 = Attestation.parse(attestationData1); + Attestation.State memory attestation2 = Attestation.parse(attestationData2); + + // Test that attestations are conflicting + if (!Attestation.areConflicting(attestation2, attestation1)) { + revert DisputeManagerNonConflictingAttestations( + attestation1.requestCID, + attestation1.responseCID, + attestation1.subgraphDeploymentId, + attestation2.requestCID, + attestation2.responseCID, + attestation2.subgraphDeploymentId + ); + } + + // Create the disputes + // The deposit is zero for conflicting attestations + bytes32 dId1 = _createQueryDisputeWithAttestation(fisherman, 0, attestation1, attestationData1); + bytes32 dId2 = _createQueryDisputeWithAttestation(fisherman, 0, attestation2, attestationData2); + + // Store the linked disputes to be resolved + disputes[dId1].relatedDisputeId = dId2; + disputes[dId2].relatedDisputeId = dId1; + + // Emit event that links the two created disputes + emit DisputeLinked(dId1, dId2); + + return (dId1, dId2); + } + + /** + * @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 + * 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 + * @param slashAmount Amount of tokens to slash from the indexer + */ + function acceptDispute( + bytes32 disputeId, + uint256 slashAmount + ) external override onlyArbitrator onlyPendingDispute(disputeId) { + Dispute storage dispute = disputes[disputeId]; + + // store the dispute status + dispute.status = IDisputeManager.DisputeStatus.Accepted; + + // Slash + uint256 tokensToReward = _slashIndexer(dispute.indexer, slashAmount); + + // Give the fisherman their reward and their deposit back + TokenUtils.pushTokens(GRAPH_TOKEN, dispute.fisherman, tokensToReward + dispute.deposit); + + if (_isDisputeInConflict(dispute)) { + rejectDispute(dispute.relatedDisputeId); + } + + emit DisputeAccepted(disputeId, dispute.indexer, dispute.fisherman, dispute.deposit + tokensToReward); + } + + /** + * @dev The arbitrator draws dispute. + * @notice Ignore a dispute with Id `disputeId` + * @param disputeId Id of the dispute to be disregarded + */ + function drawDispute(bytes32 disputeId) external override onlyArbitrator onlyPendingDispute(disputeId) { + Dispute storage dispute = disputes[disputeId]; + + // Return deposit to the fisherman + TokenUtils.pushTokens(GRAPH_TOKEN, dispute.fisherman, dispute.deposit); + + // resolve related dispute if any + _drawDisputeInConflict(dispute); + + // store dispute status + dispute.status = IDisputeManager.DisputeStatus.Drawn; + + emit DisputeDrawn(disputeId, dispute.indexer, dispute.fisherman, dispute.deposit); + } + + /** + * @dev Once the dispute period ends, if the disput status remains Pending, + * the fisherman can cancel the dispute and get back their initial deposit. + * @notice Cancel a dispute with Id `disputeId` + * @param disputeId Id of the dispute to be cancelled + */ + function cancelDispute(bytes32 disputeId) external override onlyFisherman(disputeId) onlyPendingDispute(disputeId) { + Dispute storage dispute = disputes[disputeId]; + + // Check if dispute period has finished + if (block.timestamp <= dispute.createdAt + disputePeriod) { + revert DisputeManagerDisputePeriodNotFinished(); + } + + // Return deposit to the fisherman + TokenUtils.pushTokens(GRAPH_TOKEN, dispute.fisherman, dispute.deposit); + + // resolve related dispute if any + _cancelDisputeInConflict(dispute); + + // store dispute status + dispute.status = IDisputeManager.DisputeStatus.Cancelled; + } + + /** + * @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 override onlyOwner { + _setArbitrator(arbitrator); + } + + /** + * @dev Set the dispute period. + * @notice Update the dispute period to `_disputePeriod` in seconds + * @param disputePeriod Dispute period in seconds + */ + function setDisputePeriod(uint64 disputePeriod) external override { + _setDisputePeriod(disputePeriod); + } + + /** + * @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 override onlyOwner { + _setMinimumDeposit(minimumDeposit); + } + + /** + * @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 override onlyOwner { + _setFishermanRewardPercentage(percentage); + } + + /** + * @dev Set the maximum percentage that can be used for slashing indexers. + * @param maxSlashingPercentage Max percentage slashing for disputes + */ + function setMaxSlashingPercentage(uint32 maxSlashingPercentage) external override onlyOwner { + _setMaxSlashingPercentage(maxSlashingPercentage); + } + + /** + * @dev Set the subgraph service address. + * @notice Update the subgraph service to `_subgraphService` + * @param subgraphService The address of the subgraph service contract + */ + function setSubgraphService(address subgraphService) external onlyOwner { + _setSubgraphService(subgraphService); + } + + /** + * @dev Get the message hash that a indexer used to sign the receipt. + * 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 encodeReceipt(Attestation.Receipt memory receipt) external view returns (bytes32) { + return _encodeReceipt(receipt); + } + + /** + * @dev Get the verifier cut. + * @return Verifier cut in percentage (ppm) + */ + function getVerifierCut() external view returns (uint32) { + return fishermanRewardPercentage; + } + + /** + * @dev Get the dispute period. + * @return Dispute period in seconds + */ + function getDisputePeriod() external view returns (uint64) { + return disputePeriod; + } + + function areConflictingAttestations( + Attestation.State memory attestation1, + Attestation.State memory attestation2 + ) external pure returns (bool) { + return Attestation.areConflicting(attestation1, attestation2); + } + + /** + * @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 + */ + function rejectDispute(bytes32 disputeId) public override onlyArbitrator onlyPendingDispute(disputeId) { + Dispute storage dispute = disputes[disputeId]; + + // store dispute status + dispute.status = IDisputeManager.DisputeStatus.Rejected; + + // For conflicting disputes, the related dispute must be accepted + if (_isDisputeInConflict(dispute)) { + revert DisputeManagerMustAcceptRelatedDispute(disputeId, dispute.relatedDisputeId); + } + + // Burn the fisherman's deposit + TokenUtils.burnTokens(GRAPH_TOKEN, dispute.deposit); + + emit DisputeRejected(disputeId, dispute.indexer, dispute.fisherman, dispute.deposit); + } + + /** + * @dev Returns the indexer that signed an attestation. + * @param attestation Attestation + * @return indexer address + */ + function getAttestationIndexer(Attestation.State memory attestation) public view returns (address) { + // Get attestation signer. Indexers signs with the allocationId + address allocationId = _recoverSigner(attestation); + + Allocation.State memory alloc = subgraphService.getAllocation(allocationId); + if (alloc.indexer == address(0)) { + revert DisputeManagerIndexerNotFound(allocationId); + } + if (alloc.subgraphDeploymentId != attestation.subgraphDeploymentId) { + revert DisputeManagerNonMatchingSubgraphDeployment( + alloc.subgraphDeploymentId, + attestation.subgraphDeploymentId + ); + } + return alloc.indexer; + } + + /** + * @dev Return whether a dispute exists or not. + * @notice Return if dispute with Id `disputeId` exists + * @param disputeId True if dispute already exists + */ + function isDisputeCreated(bytes32 disputeId) public view override returns (bool) { + return disputes[disputeId].status != DisputeStatus.Null; + } + + /** + * @dev 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 + * @param _fisherman Creator of dispute + * @param _deposit Amount of tokens staked as deposit + * @param _attestation Attestation struct parsed from bytes + * @param _attestationData Attestation bytes submitted by the fisherman + * @return DisputeId + */ + function _createQueryDisputeWithAttestation( + address _fisherman, + uint256 _deposit, + Attestation.State memory _attestation, + bytes memory _attestationData + ) private returns (bytes32) { + // Get the indexer that signed the attestation + address indexer = getAttestationIndexer(_attestation); + + // The indexer is disputable + IHorizonStaking.Provision memory provision = GRAPH_STAKING.getProvision(indexer, address(subgraphService)); + if (provision.tokens == 0) { + revert DisputeManagerZeroTokens(); + } + + // Create a disputeId + bytes32 disputeId = keccak256( + abi.encodePacked( + _attestation.requestCID, + _attestation.responseCID, + _attestation.subgraphDeploymentId, + indexer, + _fisherman + ) + ); + + // Only one dispute for a (indexer, subgraphDeploymentId) at a time + if (isDisputeCreated(disputeId)) { + revert DisputeManagerDisputeAlreadyCreated(disputeId); + } + + // Store dispute + disputes[disputeId] = Dispute( + indexer, + _fisherman, + _deposit, + 0, // no related dispute, + DisputeType.QueryDispute, + IDisputeManager.DisputeStatus.Pending, + block.timestamp + ); + + emit QueryDisputeCreated( + disputeId, + indexer, + _fisherman, + _deposit, + _attestation.subgraphDeploymentId, + _attestationData + ); + + return disputeId; + } + + /** + * @dev Create indexing dispute internal function. + * @param _fisherman The challenger creating the dispute + * @param _deposit Amount of tokens staked as deposit + * @param _allocationId Allocation disputed + */ + function _createIndexingDisputeWithAllocation( + address _fisherman, + uint256 _deposit, + address _allocationId + ) private returns (bytes32) { + // Create a disputeId + bytes32 disputeId = keccak256(abi.encodePacked(_allocationId)); + + // Only one dispute for an allocationId at a time + if (isDisputeCreated(disputeId)) { + revert DisputeManagerDisputeAlreadyCreated(disputeId); + } + + // Allocation must exist + Allocation.State memory alloc = subgraphService.getAllocation(_allocationId); + address indexer = alloc.indexer; + if (indexer == address(0)) { + revert DisputeManagerIndexerNotFound(_allocationId); + } + + // The indexer must be disputable + IHorizonStaking.Provision memory provision = GRAPH_STAKING.getProvision(indexer, address(subgraphService)); + if (provision.tokens == 0) { + revert DisputeManagerZeroTokens(); + } + + // Store dispute + disputes[disputeId] = Dispute( + alloc.indexer, + _fisherman, + _deposit, + 0, + DisputeType.IndexingDispute, + IDisputeManager.DisputeStatus.Pending, + block.timestamp + ); + + emit IndexingDisputeCreated(disputeId, alloc.indexer, _fisherman, _deposit, _allocationId); + + return disputeId; + } + + /** + * @dev Resolve the conflicting dispute if there is any for the one passed to this function. + * @param _dispute Dispute + * @return True if resolved + */ + function _drawDisputeInConflict(Dispute memory _dispute) private returns (bool) { + if (_isDisputeInConflict(_dispute)) { + bytes32 relatedDisputeId = _dispute.relatedDisputeId; + Dispute storage relatedDispute = disputes[relatedDisputeId]; + relatedDispute.status = IDisputeManager.DisputeStatus.Drawn; + return true; + } + return false; + } + + /** + * @dev Cancel the conflicting dispute if there is any for the one passed to this function. + * @param _dispute Dispute + * @return True if cancelled + */ + function _cancelDisputeInConflict(Dispute memory _dispute) private returns (bool) { + if (_isDisputeInConflict(_dispute)) { + bytes32 relatedDisputeId = _dispute.relatedDisputeId; + Dispute storage relatedDispute = disputes[relatedDisputeId]; + relatedDispute.status = IDisputeManager.DisputeStatus.Cancelled; + return true; + } + return false; + } + + /** + * @dev Pull deposit from submitter account. + * @param _deposit Amount of tokens to deposit + */ + function _pullSubmitterDeposit(uint256 _deposit) private { + // Ensure that fisherman has staked at least the minimum amount + if (_deposit < minimumDeposit) { + revert DisputeManagerInsufficientDeposit(_deposit, minimumDeposit); + } + + // Transfer tokens to deposit from fisherman to this contract + TokenUtils.pullTokens(GRAPH_TOKEN, msg.sender, _deposit); + } + + /** + * @dev Make the subgraph service 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 _slashAmount Amount of tokens to slash from the indexer + */ + function _slashIndexer(address _indexer, uint256 _slashAmount) private returns (uint256 rewardsAmount) { + // Get slashable amount for indexer + IHorizonStaking.Provision memory provision = GRAPH_STAKING.getProvision(_indexer, address(subgraphService)); + uint256 totalProvisionTokens = provision.tokens + provision.delegatedTokens; // slashable tokens + + // Get slash amount + uint256 maxSlashAmount = uint256(maxSlashingPercentage).mulPPM(totalProvisionTokens); + if (_slashAmount == 0) { + revert DisputeManagerInvalidSlashAmount(_slashAmount); + } + + if (_slashAmount > maxSlashAmount) { + revert DisputeManagerInvalidSlashAmount(_slashAmount); + } + + // Rewards amount can only be extracted from service poriver tokens so + // we grab the minimum between the slash amount and indexer's tokens + uint256 maxRewardableTokens = Math.min(_slashAmount, provision.tokens); + rewardsAmount = uint256(fishermanRewardPercentage).mulPPM(maxRewardableTokens); + + subgraphService.slash(_indexer, abi.encode(_slashAmount, rewardsAmount)); + return rewardsAmount; + } + + /** + * @dev Internal: Set the arbitrator address. + * @notice Update the arbitrator to `_arbitrator` + * @param _arbitrator The address of the arbitration contract or party + */ + function _setArbitrator(address _arbitrator) private { + if (_arbitrator == address(0)) { + revert DisputeManagerInvalidZeroAddress(); + } + arbitrator = _arbitrator; + emit ArbitratorSet(arbitrator); + } + + /** + * @dev Internal: Set the dispute period. + * @notice Update the dispute period to `_disputePeriod` in seconds + * @param _disputePeriod Dispute period in seconds + */ + function _setDisputePeriod(uint64 _disputePeriod) private { + if (_disputePeriod == 0) { + revert DisputeManagerDisputePeriodZero(); + } + disputePeriod = _disputePeriod; + emit DisputePeriodSet(disputePeriod); + } + + /** + * @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 + */ + function _setMinimumDeposit(uint256 _minimumDeposit) private { + if (_minimumDeposit == 0) { + revert DisputeManagerInvalidMinimumDeposit(_minimumDeposit); + } + minimumDeposit = _minimumDeposit; + emit MinimumDepositSet(minimumDeposit); + } + + /** + * @dev Internal: 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) private { + // Must be within 0% to 100% (inclusive) + if (!PPMMath.isValidPPM(_percentage)) { + revert DisputeManagerInvalidFishermanReward(_percentage); + } + fishermanRewardPercentage = _percentage; + emit FishermanRewardPercentageSet(fishermanRewardPercentage); + } + + /** + * @dev Internal: Set the maximum percentage that can be used for slashing indexers. + * @param _maxSlashingPercentage Max percentage slashing for disputes + */ + function _setMaxSlashingPercentage(uint32 _maxSlashingPercentage) private { + // Must be within 0% to 100% (inclusive) + if (!PPMMath.isValidPPM(_maxSlashingPercentage)) { + revert DisputeManagerInvalidMaxSlashingPercentage(_maxSlashingPercentage); + } + maxSlashingPercentage = _maxSlashingPercentage; + emit MaxSlashingPercentageSet(maxSlashingPercentage); + } + + /** + * @dev Internal: Set the subgraph service address. + * @notice Update the subgraph service to `_subgraphService` + * @param _subgraphService The address of the subgraph service contract + */ + function _setSubgraphService(address _subgraphService) private { + if (_subgraphService == address(0)) { + revert DisputeManagerInvalidZeroAddress(); + } + subgraphService = ISubgraphService(_subgraphService); + emit SubgraphServiceSet(_subgraphService); + } + + /** + * @dev Returns whether the dispute is for a conflicting attestation or not. + * @param _dispute Dispute + * @return True conflicting attestation dispute + */ + function _isDisputeInConflict(Dispute memory _dispute) private view returns (bool) { + bytes32 relatedId = _dispute.relatedDisputeId; + // this is so the check returns false when rejecting the related dispute. + return relatedId != 0 && disputes[relatedId].status == IDisputeManager.DisputeStatus.Pending; + } +} diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol new file mode 100644 index 000000000..350d96566 --- /dev/null +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity ^0.8.24; + +import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; +import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; + +abstract contract DisputeManagerV1Storage { + // -- State -- + + ISubgraphService public subgraphService; + + // The arbitrator is solely in control of arbitrating disputes + address public arbitrator; + + // dispute period in seconds + uint64 public disputePeriod; + + // Minimum deposit required to create a Dispute + uint256 public minimumDeposit; + + // 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; + + // Maximum percentage of indexer stake that can be slashed on a dispute + // Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) + uint32 public maxSlashingPercentage; + + // Disputes created : disputeID => Dispute + // disputeID - check creation functions to see how disputeID is built + mapping(bytes32 disputeID => IDisputeManager.Dispute dispute) public disputes; +} diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol new file mode 100644 index 000000000..9489373ab --- /dev/null +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; +import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; +import { ITAPVerifier } from "./interfaces/ITAPVerifier.sol"; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { DataService } from "./data-service/DataService.sol"; +import { DataServicePausable } from "./data-service/extensions/DataServicePausable.sol"; +import { DataServiceRescuable } from "./data-service/extensions/DataServiceRescuable.sol"; +import { DataServiceFees } from "./data-service/extensions/DataServiceFees.sol"; +import { Directory } from "./utilities/Directory.sol"; +import { AllocationManager } from "./utilities/AllocationManager.sol"; +import { SubgraphServiceV1Storage } from "./SubgraphServiceStorage.sol"; + +import { PPMMath } from "./data-service/libraries/PPMMath.sol"; +import { Allocation } from "./libraries/Allocation.sol"; +import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; + +// TODO: contract needs to be upgradeable +contract SubgraphService is + Ownable, + DataService, + DataServicePausable, + DataServiceRescuable, + DataServiceFees, + Directory, + AllocationManager, + SubgraphServiceV1Storage, + ISubgraphService +{ + using PPMMath for uint256; + using Allocation for mapping(address => Allocation.State); + + event QueryFeesRedeemed( + address serviceProvider, + address payer, + uint256 tokensCollected, + uint256 tokensCurators, + uint256 tokensSubgraphService + ); + + error SubgraphServiceEmptyUrl(); + error SubgraphServiceInconsistentRAVTokens(uint256 tokens, uint256 tokensCollected); + error SubgraphServiceInvalidPaymentType(IGraphPayments.PaymentTypes feeType); + error SubgraphServiceIndexerAlreadyRegistered(); + error SubgraphServiceIndexerNotRegistered(address indexer); + error SubgraphServiceInconsistentCollection(uint256 tokensExpected, uint256 tokensCollected); + + modifier onlyRegisteredIndexer(address indexer) { + if (indexers[indexer].registeredAt == 0) { + revert SubgraphServiceIndexerNotRegistered(indexer); + } + _; + } + + constructor( + address graphController, + address disputeManager, + address tapVerifier, + address curation, + uint256 minimumProvisionTokens + ) + Ownable(msg.sender) + DataService(graphController) + Directory(address(this), tapVerifier, disputeManager, curation) + AllocationManager("SubgraphService", "1.0") + { + _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); + } + + function register( + address indexer, + bytes calldata data + ) external override onlyProvisionAuthorized(indexer) whenNotPaused { + (string memory url, string memory geohash) = abi.decode(data, (string, string)); + + // Must provide a URL + if (bytes(url).length == 0) { + revert SubgraphServiceEmptyUrl(); + } + + // Only allow registering once + if (indexers[indexer].registeredAt != 0) { + revert SubgraphServiceIndexerAlreadyRegistered(); + } + + // Register the indexer + indexers[indexer] = Indexer({ registeredAt: block.timestamp, url: url, geoHash: geohash }); + + // Ensure the service provider created a valid provision for the data service + // and accept it in the staking contract + _acceptProvision(indexer); + + emit ServiceProviderRegistered(indexer); + } + + function acceptProvision( + address indexer, + bytes calldata + ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + _acceptProvision(indexer); + } + + function startService( + address indexer, + bytes calldata data + ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + (bytes32 subgraphDeploymentId, uint256 tokens, address allocationId, bytes memory allocationProof) = abi.decode( + data, + (bytes32, uint256, address, bytes) + ); + _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof); + emit ServiceStarted(indexer); + } + + function collectServicePayment( + address indexer, + bytes calldata data + ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + (address allocationId, bytes32 poi) = abi.decode(data, (address, bytes32)); + uint256 rewards = _collectPOIRewards(allocationId, poi); + emit ServicePaymentCollected(indexer, rewards); + } + + function stopService( + address indexer, + bytes calldata data + ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + address allocationId = abi.decode(data, (address)); + _closeAllocation(allocationId); + emit ServiceStopped(indexer); + } + + function resizeAllocation( + address indexer, + address allocationId, + uint256 tokens + ) external onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + _resizeAllocation(allocationId, tokens); + } + + // TODO: Does this design allow custom payment types?! + function redeem( + address indexer, + IGraphPayments.PaymentTypes feeType, + bytes calldata data + ) external override onlyRegisteredIndexer(indexer) whenNotPaused { + uint256 feesCollected = 0; + + if (feeType == IGraphPayments.PaymentTypes.QueryFee) { + feesCollected = _redeemQueryFees(abi.decode(data, (ITAPVerifier.SignedRAV))); + } else { + revert SubgraphServiceInvalidPaymentType(feeType); + } + + emit ServiceFeesRedeemed(indexer, feeType, feesCollected); + } + + function slash(address indexer, bytes calldata data) external override onlyDisputeManager whenNotPaused { + (uint256 tokens, uint256 reward) = abi.decode(data, (uint256, uint256)); + GRAPH_STAKING.slash(indexer, tokens, reward, address(DISPUTE_MANAGER)); + emit ServiceProviderSlashed(indexer, tokens); + } + + function migrateLegacyAllocation( + address indexer, + address allocationId, + bytes32 subgraphDeploymentID + ) external onlyOwner { + _migrateLegacyAllocation(indexer, allocationId, subgraphDeploymentID); + } + + function setPauseGuardian(address pauseGuardian, bool allowed) external onlyOwner { + _setPauseGuardian(pauseGuardian, allowed); + } + + function getAllocation(address allocationId) external view override returns (Allocation.State memory) { + return allocations[allocationId]; + } + + function getLegacyAllocation(address allocationId) external view returns (LegacyAllocation.State memory) { + return legacyAllocations[allocationId]; + } + + function encodeAllocationProof(address _indexer, address _allocationId) external view returns (bytes32) { + return _encodeAllocationProof(_indexer, _allocationId); + } + + // -- Data service parameter getters -- + function _getThawingPeriodRange() internal view override returns (uint64 min, uint64 max) { + uint64 disputePeriod = DISPUTE_MANAGER.getDisputePeriod(); + return (disputePeriod, type(uint64).max); + } + + function _getVerifierCutRange() internal view override returns (uint32 min, uint32 max) { + uint32 verifierCut = DISPUTE_MANAGER.getVerifierCut(); + return (verifierCut, type(uint32).max); + } + + function _redeemQueryFees(ITAPVerifier.SignedRAV memory _signedRAV) private returns (uint256 feesCollected) { + address indexer = _signedRAV.rav.serviceProvider; + address allocationId = abi.decode(_signedRAV.rav.metadata, (address)); + + // release expired stake claims + _releaseStake(IGraphPayments.PaymentTypes.QueryFee, indexer, 0); + + // validate RAV and calculate tokens to collect + address payer = TAP_VERIFIER.verify(_signedRAV); + uint256 tokens = _signedRAV.rav.valueAggregate; + uint256 tokensAlreadyCollected = tokensCollected[indexer][payer]; + if (tokens <= tokensAlreadyCollected) { + revert SubgraphServiceInconsistentRAVTokens(tokens, tokensAlreadyCollected); + } + uint256 tokensToCollect = tokens - tokensAlreadyCollected; + uint256 tokensCurators = 0; + uint256 tokensSubgraphService = 0; + + if (tokensToCollect > 0) { + // lock stake as economic security for fees + // block scope to avoid 'stack too deep' error + { + uint256 tokensToLock = tokensToCollect * stakeToFeesRatio; + uint256 unlockTimestamp = block.timestamp + DISPUTE_MANAGER.getDisputePeriod(); + _lockStake(IGraphPayments.PaymentTypes.QueryFee, indexer, tokensToLock, unlockTimestamp); + } + + // get subgraph deployment id - reverts if allocation is not found + bytes32 subgraphDeploymentId = allocations.get(allocationId).subgraphDeploymentId; + + // calculate service and curator cuts + // TODO: note we don't let curation cut round down to zero + PaymentFee memory feePercentages = _getQueryFeesPaymentFees(subgraphDeploymentId); + tokensSubgraphService = tokensToCollect.mulPPM(feePercentages.servicePercentage); + tokensCurators = tokensToCollect.mulPPMRoundUp(feePercentages.curationPercentage); + uint256 totalCut = tokensSubgraphService + tokensCurators; + + // collect fees + uint256 balanceBefore = GRAPH_TOKEN.balanceOf(address(this)); + GRAPH_PAYMENTS.collect(payer, indexer, tokensToCollect, IGraphPayments.PaymentTypes.QueryFee, totalCut); + uint256 balanceAfter = GRAPH_TOKEN.balanceOf(address(this)); + if (balanceBefore + totalCut != balanceAfter) { + revert SubgraphServiceInconsistentCollection(balanceBefore + totalCut, balanceAfter); + } + tokensCollected[indexer][payer] = tokens; + + // distribute curation cut to curators + if (tokensCurators > 0) { + // we are about to change subgraph signal so we take rewards snapshot + GRAPH_REWARDS_MANAGER.onSubgraphSignalUpdate(subgraphDeploymentId); + + // Send GRT and bookkeep by calling collect() + GRAPH_TOKEN.transfer(address(CURATION), tokensCurators); + CURATION.collect(subgraphDeploymentId, tokensCurators); + } + } + + emit QueryFeesRedeemed(indexer, payer, tokensToCollect, tokensCurators, tokensSubgraphService); + return tokensToCollect; + } + + function _getQueryFeesPaymentFees(bytes32 _subgraphDeploymentId) private view returns (PaymentFee memory) { + PaymentFee memory feePercentages = paymentFees[IGraphPayments.PaymentTypes.QueryFee]; + + // Only pay curation fees if the subgraph is curated + if (!CURATION.isCurated(_subgraphDeploymentId)) { + feePercentages.curationPercentage = 0; + } + + return feePercentages; + } +} diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol new file mode 100644 index 000000000..27ebc13ff --- /dev/null +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; +import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; + +abstract contract SubgraphServiceV1Storage { + /// @notice Service providers registered in the data service + mapping(address indexer => ISubgraphService.Indexer details) public indexers; + + // -- Fees -- + // multiplier for how many tokens back collected query fees + uint256 public stakeToFeesRatio; + + /// @notice The fees cut taken by the subgraph service + mapping(IGraphPayments.PaymentTypes paymentType => ISubgraphService.PaymentFee paymentFees) public paymentFees; + + mapping(address indexer => mapping(address payer => uint256 tokens)) public tokensCollected; +} diff --git a/packages/subgraph-service/contracts/TAPVerifier.sol b/packages/subgraph-service/contracts/TAPVerifier.sol new file mode 100644 index 000000000..e7b3d5a7f --- /dev/null +++ b/packages/subgraph-service/contracts/TAPVerifier.sol @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { ITAPVerifier } from "./interfaces/ITAPVerifier.sol"; + +import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; + +/** + * @title TAPVerifier + * @dev A contract for verifying receipt aggregation vouchers. + */ +contract TAPVerifier is EIP712, ITAPVerifier { + bytes32 private constant EIP712_RAV_TYPEHASH = + keccak256( + "ReceiptAggregateVoucher(address dataService, address serviceProvider,uint64 timestampNs,uint128 valueAggregate,bytes metadata)" + ); + + // The duration (in seconds) in which a signer is thawing before they can be revoked + uint256 public immutable REVOKE_SIGNER_THAWING_PERIOD; + + // Map of signer to authorized signer information + mapping(address signer => SenderAuthorization authorizedSigner) public authorizedSigners; + + /** + * @dev Emitted when a signer is authorized to sign RAVs for a sender. + */ + event AuthorizeSigner(address indexed signer, address indexed sender); + /** + * @dev Emitted when a thaw request is made for authorized signer + */ + event ThawSigner(address indexed sender, address indexed authorizedSigner, uint256 thawEndTimestamp); + + /** + * @dev Emitted when the thawing of a signer is cancelled + */ + event CancelThawSigner(address indexed sender, address indexed authorizedSigner, uint256 thawEndTimestamp); + + /** + * @dev Emitted when a authorized signer has been revoked + */ + event RevokeAuthorizedSigner(address indexed sender, address indexed authorizedSigner); + + error TAPVerifierInvalidCaller(address sender, address expected); + error TAPVerifierInvalidSignerProof(); + error TAPVerifierAlreadyAuthorized(address signer, address authorizingSender); + error TAPVerifierNotAuthorized(address signer, address sender); + error TAPVerifierNotThawing(); + error TAPVerifierStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); + + /** + * @dev Constructs a new instance of the TAPVerifier contract. + */ + constructor(string memory eip712Name, string memory eip712Version) EIP712(eip712Name, eip712Version) {} + + /** + * @dev Authorizes a signer to sign RAVs for the sender. + * @param signer Address of the authorized signer. + * @param proof The proof provided by the signer to authorize the sender, consisting of packed (chainID, proof deadline, sender address). + * @dev The proof deadline is the timestamp at which the proof expires. The proof is susceptible to replay attacks until the deadline is reached. + * @notice REVERT with error: + * - SignerAlreadyAuthorized: Signer is currently authorized for a sender + * - InvalidSignerProof: The provided signer proof is invalid + */ + function authorizeSigner(address signer, uint256 proofDeadline, bytes calldata proof) external { + if (authorizedSigners[signer].sender != address(0)) { + revert TAPVerifierAlreadyAuthorized(signer, authorizedSigners[signer].sender); + } + + _verifyAuthorizedSignerProof(proof, proofDeadline, signer); + + authorizedSigners[signer].sender = msg.sender; + authorizedSigners[signer].thawEndTimestamp = 0; + emit AuthorizeSigner(signer, msg.sender); + } + + /** + * @dev Starts thawing a signer to be removed from the authorized signers list. + * @param signer Address of the signer to remove. + * @notice WARNING: Thawing a signer alerts receivers that signatures from that signer will soon be deemed invalid. + * Receivers without existing signed receipts or RAVs from this signer should treat them as unauthorized. + * Those with existing signed documents from this signer should work towards settling their engagements. + * Once a signer is thawed, they should be viewed as revoked regardless of their revocation status. + * @notice REVERT with error: + * - SignerNotAuthorizedBySender: The provided signer is either not authorized or + * authorized by a different sender + */ + function thawSigner(address signer) external { + SenderAuthorization storage authorization = authorizedSigners[signer]; + + if (authorization.sender != msg.sender) { + revert TAPVerifierNotAuthorized(signer, authorizedSigners[signer].sender); + } + + authorization.thawEndTimestamp = block.timestamp + REVOKE_SIGNER_THAWING_PERIOD; + emit ThawSigner(authorization.sender, signer, authorization.thawEndTimestamp); + } + + /** + * @dev Stops thawing a signer. + * @param signer Address of the signer to stop thawing. + * @notice REVERT with error: + * - SignerNotAuthorizedBySender: The provided signer is either not authorized or + * authorized by a different sender + */ + function cancelThawSigner(address signer) external { + SenderAuthorization storage authorization = authorizedSigners[signer]; + + if (authorization.sender != msg.sender) { + revert TAPVerifierNotAuthorized(signer, authorizedSigners[signer].sender); + } + + authorization.thawEndTimestamp = 0; + emit CancelThawSigner(authorization.sender, signer, authorization.thawEndTimestamp); + } + + /** + * @dev Revokes a signer from the authorized signers list if thawed. + * @param signer Address of the signer to remove. + * @notice REVERT with error: + * - SignerNotAuthorizedBySender: The provided signer is either not authorized or + * authorized by a different sender + * - SignerNotThawing: No thaw was initiated for the provided signer + * - SignerStillThawing: ThawEndTimestamp has not been reached + * for provided signer + */ + function revokeAuthorizedSigner(address signer) external { + SenderAuthorization storage authorization = authorizedSigners[signer]; + + if (authorization.sender != msg.sender) { + revert TAPVerifierNotAuthorized(signer, authorizedSigners[signer].sender); + } + + if (authorization.thawEndTimestamp == 0) { + revert TAPVerifierNotThawing(); + } + + if (authorization.thawEndTimestamp > block.timestamp) { + revert TAPVerifierStillThawing({ + currentTimestamp: block.timestamp, + thawEndTimestamp: authorization.thawEndTimestamp + }); + } + + delete authorizedSigners[signer]; + emit RevokeAuthorizedSigner(authorization.sender, signer); + } + + /** + * @notice Verify validity of a SignedRAV + * @dev Caller must be the data service the RAV was issued to. + * @param signedRAV The SignedRAV containing the RAV and its signature. + * @return The address of the signer. + * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. + */ + function verify(SignedRAV calldata signedRAV) external view returns (address) { + if (signedRAV.rav.dataService != msg.sender) { + revert TAPVerifierInvalidCaller(msg.sender, signedRAV.rav.dataService); + } + return recover(signedRAV); + } + + /** + * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). + * @param signedRAV The SignedRAV containing the RAV and its signature. + * @return The address of the signer. + * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. + */ + function recover(SignedRAV calldata signedRAV) public view returns (address) { + bytes32 messageHash = encodeRAV(signedRAV.rav); + return ECDSA.recover(messageHash, signedRAV.signature); + } + + /** + * @dev Computes the hash of a ReceiptAggregateVoucher (RAV). + * @param rav The RAV for which to compute the hash. + * @return The hash of the RAV. + */ + function encodeRAV(ReceiptAggregateVoucher calldata rav) public view returns (bytes32) { + return + _hashTypedDataV4( + keccak256( + abi.encode( + EIP712_RAV_TYPEHASH, + rav.dataService, + rav.serviceProvider, + rav.timestampNs, + rav.valueAggregate + ) + ) + ); + } + + /** + * @dev Verifies a proof that authorizes the sender to authorize the signer. + * @param _proof The proof provided by the signer to authorize the sender. + * @param _signer The address of the signer being authorized. + * @notice REVERT with error: + * - InvalidSignerProof: If the given proof is not valid + */ + function _verifyAuthorizedSignerProof(bytes calldata _proof, uint256 _proofDeadline, address _signer) private view { + // Verify that the proof deadline has not passed + if (block.timestamp > _proofDeadline) { + revert TAPVerifierInvalidSignerProof(); + } + + // Generate the hash of the sender's address + bytes32 messageHash = keccak256(abi.encodePacked(block.chainid, _proofDeadline, msg.sender)); + + // Generate the digest to be signed by the signer + bytes32 digest = MessageHashUtils.toEthSignedMessageHash(messageHash); + + // Verify that the recovered signer matches the expected signer + if (ECDSA.recover(digest, _proof) != _signer) { + revert TAPVerifierInvalidSignerProof(); + } + } +} diff --git a/packages/subgraph-service/contracts/data-service/DataService.sol b/packages/subgraph-service/contracts/data-service/DataService.sol new file mode 100644 index 000000000..52f1e25b5 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/DataService.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataService } from "./IDataService.sol"; + +import { GraphDirectory } from "./GraphDirectory.sol"; +import { DataServiceV1Storage } from "./DataServiceStorage.sol"; +import { ProvisionManager } from "./utilities/ProvisionManager.sol"; + +/** + * @title Implementation of the {IDataService} interface. + * @dev This implementation provides base functionality for a data service: + * - GraphDirectory, allows the data service to interact with Graph Horizon contracts + * - ProvisionManager, provides functionality to manage provisions + * + * The derived contract should add functionality that implements the interfaces described in {IDataService}. + */ +abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1Storage, IDataService { + /** + * @dev Addresses in GraphDirectory are immutables, they can only be set in this constructor. + * @param controller The address of the Graph Horizon controller contract. + */ + constructor(address controller) GraphDirectory(controller) {} + + /** + * @notice Verifies and accepts the provision of a service provider in the {Graph Horizon staking + * contract}. + * @dev This internal function is a wrapper around {ProvisionManager-checkAndAcceptProvision} + * that ensures the event {ProvisionAccepted} is emitted when called from different contexts. + * + * Emits a {ProvisionAccepted} event. + * + * @param _serviceProvider The address of the service provider. + */ + function _acceptProvision(address _serviceProvider) internal { + _checkAndAcceptProvision(_serviceProvider); + emit ProvisionAccepted(_serviceProvider); + } +} diff --git a/packages/subgraph-service/contracts/data-service/DataServiceStorage.sol b/packages/subgraph-service/contracts/data-service/DataServiceStorage.sol new file mode 100644 index 000000000..3cb7e0b86 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/DataServiceStorage.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +abstract contract DataServiceV1Storage { + /// @dev Gap to allow adding variables in future upgrades + uint256[50] private __gap; +} diff --git a/packages/subgraph-service/contracts/data-service/GraphDirectory.sol b/packages/subgraph-service/contracts/data-service/GraphDirectory.sol new file mode 100644 index 000000000..f35a7a663 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/GraphDirectory.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +// import { IGraphTokenGateway } from "@graphprotocol/contracts/contracts/gateway/IGraphTokenGateway.sol"; +import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; +import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; +import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; + +abstract contract GraphDirectory { + IController public immutable GRAPH_CONTROLLER; + IHorizonStaking public immutable GRAPH_STAKING; + IEpochManager public immutable GRAPH_EPOCH_MANAGER; + IGraphToken public immutable GRAPH_TOKEN; + // IGraphTokenGateway public immutable graphTokenGateway; + IGraphEscrow public immutable GRAPH_ESCROW; + IGraphPayments public immutable GRAPH_PAYMENTS; + IRewardsManager public immutable GRAPH_REWARDS_MANAGER; + + event GraphDirectoryInitialized( + IController graphController, + IHorizonStaking graphStaking, + IEpochManager graphEpochManager, + IGraphToken graphToken, + // address graphTokenGateway, + IGraphEscrow graphEscrow, + IGraphPayments graphPayments, + IRewardsManager graphRewardsManager + ); + + constructor(address controller) { + GRAPH_CONTROLLER = IController(controller); + GRAPH_STAKING = IHorizonStaking(GRAPH_CONTROLLER.getContractProxy(keccak256("Staking"))); + GRAPH_EPOCH_MANAGER = IEpochManager(GRAPH_CONTROLLER.getContractProxy(keccak256("EpochManager"))); + GRAPH_TOKEN = IGraphToken(GRAPH_CONTROLLER.getContractProxy(keccak256("GraphToken"))); + // graphTokenGateway = graphController.getContractProxy(keccak256("GraphTokenGateway")); + GRAPH_ESCROW = IGraphEscrow(GRAPH_CONTROLLER.getContractProxy(keccak256("GraphEscrow"))); + GRAPH_PAYMENTS = IGraphPayments(GRAPH_CONTROLLER.getContractProxy(keccak256("GraphPayments"))); + GRAPH_REWARDS_MANAGER = IRewardsManager(GRAPH_CONTROLLER.getContractProxy(keccak256("RewardsManager"))); + emit GraphDirectoryInitialized( + GRAPH_CONTROLLER, + GRAPH_STAKING, + GRAPH_EPOCH_MANAGER, + GRAPH_TOKEN, + // graphTokenGateway, + GRAPH_ESCROW, + GRAPH_PAYMENTS, + GRAPH_REWARDS_MANAGER + ); + } +} diff --git a/packages/subgraph-service/contracts/data-service/IDataService.sol b/packages/subgraph-service/contracts/data-service/IDataService.sol new file mode 100644 index 000000000..0e598b2cb --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/IDataService.sol @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; + +/** + * @title Interface of the base {DataService} contract as defined by the Graph Horizon specification. + * @dev This interface provides a guardrail for data service implementations that utilize Graph Horizon. + * It's expected that implementations follow the specification however much of it is intentionally loose + * to allow for greater flexibility when designing a data service. For specifics always check the data + * service implementation. + + * In general, this is a great starting point for data services that want to use Graph Horizon + * to provide economic security for a service being provided. It assumes two main forms of retribution for + * service providers: + * - service payment, to compensate ongoing work required to serve customers requests + * - service fees, earnt by serving customer requests, ideally leveraging {GraphPayments} to collect fees from the payer + * + * TIP: TODO: link to data service framework documentation + */ +interface IDataService { + /** + * @notice Emitted when a service provider is registered with the data service. + * @param serviceProvider The address of the service provider. + */ + event ServiceProviderRegistered(address indexed serviceProvider); + + /** + * @notice Emitted when a service provider accepts a provision in {Graph Horizon staking contract}. + * @param serviceProvider The address of the service provider. + */ + event ProvisionAccepted(address indexed serviceProvider); + + /** + * @notice Emitted when a service provider starts providing the service. + * @param serviceProvider The address of the service provider. + */ + event ServiceStarted(address indexed serviceProvider); + + /** + * @notice Emitted when a service provider stops providing the service. + * @param serviceProvider The address of the service provider. + */ + event ServiceStopped(address indexed serviceProvider); + + /** + * @notice Emitted when a service provider collects payment for the service being provided. + * @param serviceProvider The address of the service provider. + * @param tokens The amount of tokens collected. + */ + event ServicePaymentCollected(address indexed serviceProvider, uint256 tokens); + + /** + * @notice Emitted when a service provider redeems fees. + * @param serviceProvider The address of the service provider. + * @param feeType The type of fee to redeem as defined in {GraphPayments}. + * @param tokens The amount of tokens redeemed. + */ + event ServiceFeesRedeemed( + address indexed serviceProvider, + IGraphPayments.PaymentTypes indexed feeType, + uint256 tokens + ); + + /** + * @notice Emitted when a service provider is slashed. + * @param serviceProvider The address of the service provider. + * @param tokens The amount of tokens slashed. + */ + event ServiceProviderSlashed(address indexed serviceProvider, uint256 tokens); + + /** + * @notice Thrown to signal that a feature is not implemented by a data service. + */ + error DataServiceFeatureNotImplemented(); + + /** + * @notice Registers a service provider with the data service. The service provider can now + * start providing the service. + * @dev Before registering, the service provider must have created a provision in the + * Graph Horizon staking contract with parameters that are compatible with the data service. + * + * Verifies the provision parameters and marks it as accepted it in the Graph Horizon + * staking contract using {_acceptProvision}. + * + * Emits a {ServiceProviderRegistered} event. + * + * NOTE: Failing to accept the provision will result in the service provider operating + * on an unverified provision. Depending on of the data service this can be a security + * risk as the protocol won't be able to guarantee economic security for the consumer. + * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. + */ + function register(address serviceProvider, bytes calldata data) external; + + /** + * @notice Accepts the provision of a service provider in the {Graph Horizon staking + * contract}. + * @dev Provides a way for the data service to revalidate and reaccept a provision that + * had a parameter change. Should call {_acceptProvision}. + * + * Emits a {ProvisionAccepted} event. + * + * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. + */ + function acceptProvision(address serviceProvider, bytes calldata data) external; + + /** + * @notice Service provider starts providing the service. + * @dev Emits a {ServiceStarted} event. + * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. + */ + function startService(address serviceProvider, bytes calldata data) external; + + /** + * @notice Service provider collects payment for the service being provided. + * @dev This is payment owed to a service provided for ongoing work required to fullfil + * customer requests. How the funds for the payment are procured is up to the data service. + * + * Emits a {ServicePaymentCollected} event. + * + * NOTE: Data services that are vetted by the Graph Council might qualify for a portion of + * the protocol issuance to cover these payments. In this case, the funds are taken by + * interacting with the rewards manager contract. + * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. + */ + function collectServicePayment(address serviceProvider, bytes calldata data) external; + + /** + * @notice Service provider stops providing the service. + * @dev Emits a {ServiceStopped} event. + * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. + */ + function stopService(address serviceProvider, bytes calldata data) external; + + /** + * @notice Redeeems fees earnt by the service provider. + * @dev The implementation of this function is expected to interact with {GraphPayments} + * to collect fees from the service payer, which is done via {IGraphPayments-collect}. + * @param serviceProvider The address of the service provider. + * + * Emits a {ServicePaymentRedeemed} event. + * + * @param feeType The type of fee to redeem as defined in {GraphPayments}. + * @param data Custom data, usage defined by the data service. + */ + function redeem(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external; + + /** + * @notice Slash a service provider for misbehaviour. + * @dev To slash the service provider's provision the function should call + * {Staking-slash}. + * + * Emits a {ServiceProviderSlashed} event. + * + * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. + */ + function slash(address serviceProvider, bytes calldata data) external; +} diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServiceFees.sol b/packages/subgraph-service/contracts/data-service/extensions/DataServiceFees.sol new file mode 100644 index 000000000..583f01efa --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/extensions/DataServiceFees.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataServiceFees } from "./IDataServiceFees.sol"; +import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; + +import { DataService } from "../DataService.sol"; +import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol"; + +import { ProvisionTracker } from "../libraries/ProvisionTracker.sol"; + +abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDataServiceFees { + using ProvisionTracker for mapping(address => uint256); + + event StakeClaimLocked( + address indexed serviceProvider, + bytes32 indexed claimId, + uint256 tokens, + uint256 unlockTimestamp + ); + event StakeClaimReleased( + address indexed serviceProvider, + bytes32 indexed claimId, + uint256 tokens, + uint256 releaseAt + ); + + error DataServiceFeesClaimNotFound(bytes32 claimId); + + function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external virtual { + _releaseStake(feeType, msg.sender, n); + } + + /// @notice Release expired stake claims for a service provider + /// @param _n The number of stake claims to release, or 0 to release all + function _releaseStake(IGraphPayments.PaymentTypes _feeType, address _serviceProvider, uint256 _n) internal { + bool releaseAll = _n == 0; + + // check the stake claims list + // TODO: evaluate replacing with OZ DoubleEndedQueue + bytes32 head = claimsLists[_feeType][_serviceProvider].head; + while (head != bytes32(0) && (releaseAll || _n > 0)) { + StakeClaim memory claim = _getStakeClaim(head); + + if (block.timestamp >= claim.releaseAt) { + // Release stake + feesProvisionTracker[_feeType].release(_serviceProvider, claim.tokens); + + // Update list and refresh pointer + StakeClaimsList storage claimsList = claimsLists[_feeType][_serviceProvider]; + claimsList.head = claim.nextClaim; + delete claims[head]; + head = claimsList.head; + if (!releaseAll) _n--; + + emit StakeClaimReleased(_serviceProvider, claimsList.head, claim.tokens, claim.releaseAt); + } else { + break; + } + } + } + + function _lockStake( + IGraphPayments.PaymentTypes _feeType, + address _serviceProvider, + uint256 _tokens, + uint256 _unlockTimestamp + ) internal { + feesProvisionTracker[_feeType].lock(GRAPH_STAKING, _serviceProvider, _tokens); + + StakeClaimsList storage claimsList = claimsLists[_feeType][_serviceProvider]; + bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); + claims[claimId] = StakeClaim({ + serviceProvider: _serviceProvider, + tokens: _tokens, + createdAt: block.timestamp, + releaseAt: _unlockTimestamp, + nextClaim: bytes32(0) + }); + + claims[claimsList.tail].nextClaim = claimId; + claimsList.tail = claimId; + claimsList.nonce += 1; + + emit StakeClaimLocked(_serviceProvider, claimId, _tokens, _unlockTimestamp); + } + + function _getStakeClaim(bytes32 _claimId) private view returns (StakeClaim memory) { + StakeClaim memory claim = claims[_claimId]; + if (claim.createdAt == 0) { + revert DataServiceFeesClaimNotFound(_claimId); + } + return claim; + } + + function _buildStakeClaimId(address _serviceProvider, uint256 _nonce) private view returns (bytes32) { + return keccak256(abi.encodePacked(address(this), _serviceProvider, _nonce)); + } +} diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/subgraph-service/contracts/data-service/extensions/DataServiceFeesStorage.sol new file mode 100644 index 000000000..4296a952a --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataServiceFees } from "./IDataServiceFees.sol"; +import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; + +abstract contract DataServiceFeesV1Storage { + /// @notice List of all locked stake claims to be released to service providers + mapping(bytes32 claimId => IDataServiceFees.StakeClaim claim) public claims; + + mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => uint256 tokens)) + public feesProvisionTracker; + + /// @notice Service providers registered in the data service + mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => IDataServiceFees.StakeClaimsList list)) + public claimsLists; + + /// @dev Gap to allow adding variables in future upgrades + uint256[50] private __gap; +} diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServicePausable.sol b/packages/subgraph-service/contracts/data-service/extensions/DataServicePausable.sol new file mode 100644 index 000000000..ab0ec97c3 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/extensions/DataServicePausable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataServicePausable } from "./IDataServicePausable.sol"; + +import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; +import { DataService } from "../DataService.sol"; + +abstract contract DataServicePausable is Pausable, DataService, IDataServicePausable { + mapping(address pauseGuardian => bool allowed) public pauseGuardians; + + event PauseGuardianSet(address indexed account, bool allowed); + + error DataServicePausableNotPauseGuardian(address account); + + modifier onlyPauseGuardian() { + if (!pauseGuardians[msg.sender]) { + revert DataServicePausableNotPauseGuardian(msg.sender); + } + _; + } + + function pause() public onlyPauseGuardian whenNotPaused { + _pause(); + } + + function unpause() public onlyPauseGuardian whenPaused { + _unpause(); + } + + function _setPauseGuardian(address _pauseGuardian, bool _allowed) internal whenNotPaused { + pauseGuardians[_pauseGuardian] = _allowed; + emit PauseGuardianSet(_pauseGuardian, _allowed); + } +} diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/subgraph-service/contracts/data-service/extensions/DataServiceRescuable.sol new file mode 100644 index 000000000..7e6120783 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/extensions/DataServiceRescuable.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IDataServiceRescuable } from "./IDataServiceRescuable.sol"; + +import { DataService } from "../DataService.sol"; + +import { Denominations } from "../libraries/Denominations.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title Rescuable contract + * @dev Allows a contract to have a function to rescue tokens sent by mistake. + * The contract must implement the external rescueTokens function or similar, + * that calls this contract's _rescueTokens. + */ +abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { + mapping(address rescuer => bool allowed) public rescuers; + + /** + * @dev Tokens rescued by the user + */ + event TokensRescued(address indexed from, address indexed to, uint256 amount); + event RescuerSet(address indexed account, bool allowed); + + error DataServiceRescuableCannotRescueZero(); + error DataServiceRescuableNotRescuer(address account); + + modifier onlyRescuer() { + if (!rescuers[msg.sender]) { + revert DataServiceRescuableNotRescuer(msg.sender); + } + _; + } + + function rescueGRT(address to, uint256 amount) external onlyRescuer { + _rescueTokens(to, address(GRAPH_TOKEN), amount); + } + + function rescueETH(address payable to, uint256 amount) external onlyRescuer { + _rescueTokens(to, Denominations.NATIVE_TOKEN, amount); + } + + function _setRescuer(address _rescuer, bool _allowed) internal { + rescuers[_rescuer] = _allowed; + emit RescuerSet(_rescuer, _allowed); + } + + /** + * @dev Allows rescuing tokens sent to this contract + * @param _to Destination address to send the tokens + * @param _token Address of the token being rescued + * @param _amount Amount of tokens to pull + */ + function _rescueTokens(address _to, address _token, uint256 _amount) internal { + if (_amount == 0) revert DataServiceRescuableCannotRescueZero(); + + if (Denominations.isNativeToken(_token)) payable(_to).transfer(_amount); + else SafeERC20.safeTransfer(IERC20(_token), _to, _amount); + + emit TokensRescued(msg.sender, _to, _amount); + } +} diff --git a/packages/subgraph-service/contracts/data-service/extensions/IDataServiceFees.sol b/packages/subgraph-service/contracts/data-service/extensions/IDataServiceFees.sol new file mode 100644 index 000000000..36caf73f1 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/extensions/IDataServiceFees.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataService } from "../IDataService.sol"; +import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; + +interface IDataServiceFees is IDataService { + struct StakeClaimsList { + bytes32 head; + bytes32 tail; + uint256 nonce; + } + + /// A locked stake claim to be released to a service provider + struct StakeClaim { + address serviceProvider; + // tokens to be released with this claim + uint256 tokens; + uint256 createdAt; + // timestamp when the claim can be released + uint256 releaseAt; + // next claim in the linked list + bytes32 nextClaim; + } + + function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external; +} diff --git a/packages/subgraph-service/contracts/data-service/extensions/IDataServicePausable.sol b/packages/subgraph-service/contracts/data-service/extensions/IDataServicePausable.sol new file mode 100644 index 000000000..5b2940d6c --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/extensions/IDataServicePausable.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataService } from "../IDataService.sol"; + +interface IDataServicePausable is IDataService { + function pause() external; + function unpause() external; +} diff --git a/packages/subgraph-service/contracts/data-service/extensions/IDataServiceRescuable.sol b/packages/subgraph-service/contracts/data-service/extensions/IDataServiceRescuable.sol new file mode 100644 index 000000000..36ad6d68f --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/extensions/IDataServiceRescuable.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataService } from "../IDataService.sol"; + +interface IDataServiceRescuable is IDataService { + function rescueGRT(address to, uint256 amount) external; + function rescueETH(address payable to, uint256 amount) external; +} diff --git a/packages/subgraph-service/contracts/data-service/libraries/Denominations.sol b/packages/subgraph-service/contracts/data-service/libraries/Denominations.sol new file mode 100644 index 000000000..a5f543fb2 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/libraries/Denominations.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +/** + * @title Denominations + * @dev Provides a list of ground denominations for those tokens that cannot be represented by an ERC20. + * For now, the only needed is the native token that could be ETH, MATIC, or other depending on the layer being operated. + */ +library Denominations { + address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + + function isNativeToken(address token) internal pure returns (bool) { + return token == NATIVE_TOKEN; + } +} diff --git a/packages/subgraph-service/contracts/data-service/libraries/PPMMath.sol b/packages/subgraph-service/contracts/data-service/libraries/PPMMath.sol new file mode 100644 index 000000000..ac0f65252 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/libraries/PPMMath.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +library PPMMath { + /// @notice Maximum value in parts per million (PPM). + uint256 internal constant MAX_PPM = 1_000_000; + + error PPMMathInvalidPPM(uint256 ppm); + error PPMMathInvalidMulPPM(uint256 a, uint256 b); + + // one of a or b must be in PPM + function mulPPM(uint256 a, uint256 b) internal pure returns (uint256) { + if (!isValidPPM(a) && !isValidPPM(b)) { + revert PPMMathInvalidMulPPM(a, b); + } + return (a * b) / MAX_PPM; + } + + // Calculate the tokens after curation fees first, and subtact that, + // to prevent curation fees from rounding down to zero + // a must be in ppm + function mulPPMRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { + if (!isValidPPM(a)) { + revert PPMMathInvalidPPM(a); + } + return b - mulPPM(MAX_PPM - a, b); + } + + function isValidPPM(uint256 ppm) internal pure returns (bool) { + return ppm >= 0 && ppm <= MAX_PPM; + } +} diff --git a/packages/subgraph-service/contracts/data-service/libraries/ProvisionGetter.sol b/packages/subgraph-service/contracts/data-service/libraries/ProvisionGetter.sol new file mode 100644 index 000000000..4de039012 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/libraries/ProvisionGetter.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; + +library ProvisionGetter { + using ProvisionGetter for IHorizonStaking.Provision; + + error ProvisionGetterProvisionNotFound(address serviceProvider, address service); + + function get( + IHorizonStaking graphStaking, + address serviceProvider + ) internal view returns (IHorizonStaking.Provision memory) { + IHorizonStaking.Provision memory provision = graphStaking.getProvision(serviceProvider, address(this)); + if (provision.createdAt == 0) { + revert ProvisionGetterProvisionNotFound(serviceProvider, address(this)); + } + return provision; + } +} diff --git a/packages/subgraph-service/contracts/data-service/libraries/ProvisionTracker.sol b/packages/subgraph-service/contracts/data-service/libraries/ProvisionTracker.sol new file mode 100644 index 000000000..216bbe3dc --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/libraries/ProvisionTracker.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; + +library ProvisionTracker { + error ProvisionTrackerInsufficientTokens(uint256 tokensAvailable, uint256 tokensRequired); + + function lock( + mapping(address => uint256) storage self, + IHorizonStaking graphStaking, + address serviceProvider, + uint256 tokens + ) internal { + if (tokens == 0) return; + + uint256 tokensRequired = self[serviceProvider] + tokens; + uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this)); + if (tokensRequired > tokensAvailable) { + revert ProvisionTrackerInsufficientTokens(tokensAvailable, tokensRequired); + } + self[serviceProvider] += tokens; + } + + function release(mapping(address => uint256) storage self, address serviceProvider, uint256 tokens) internal { + if (tokens == 0) return; + + if (tokens > self[serviceProvider]) { + revert ProvisionTrackerInsufficientTokens(self[serviceProvider], tokens); + } + self[serviceProvider] -= tokens; + } + + function getTokensFree( + mapping(address => uint256) storage self, + IHorizonStaking graphStaking, + address serviceProvider + ) internal view returns (uint256) { + uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this)); + if (tokensAvailable >= self[serviceProvider]) return tokensAvailable - self[serviceProvider]; + else return 0; + } +} diff --git a/packages/subgraph-service/contracts/data-service/libraries/UintRange.sol b/packages/subgraph-service/contracts/data-service/libraries/UintRange.sol new file mode 100644 index 000000000..f98714d25 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/libraries/UintRange.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +library UintRange { + using UintRange for uint256; + + function isInRange(uint256 self, uint256 min, uint256 max) internal pure returns (bool) { + return self >= min && self <= max; + } +} diff --git a/packages/subgraph-service/contracts/data-service/utilities/ProvisionManager.sol b/packages/subgraph-service/contracts/data-service/utilities/ProvisionManager.sol new file mode 100644 index 000000000..581cff131 --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/utilities/ProvisionManager.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; + +import { GraphDirectory } from "../GraphDirectory.sol"; +import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; + +import { ProvisionGetter } from "../libraries/ProvisionGetter.sol"; +import { UintRange } from "../libraries/UintRange.sol"; + +abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage { + using ProvisionGetter for IHorizonStaking; + using UintRange for uint256; + + error ProvisionManagerInvalidProvisionTokens( + uint256 tokens, + uint256 minimumProvisionTokens, + uint256 maximumProvisionTokens + ); + error ProvisionManagerInvalidVerifierCut( + uint256 verifierCut, + uint256 minimumVerifierCut, + uint256 maximumVerifierCut + ); + error ProvisionManagerInvalidThawingPeriod( + uint64 thawingPeriod, + uint64 minimumThawingPeriod, + uint64 maximumThawingPeriod + ); + error ProvisionManagerNotAuthorized(address caller, address serviceProvider, address service); + + modifier onlyProvisionAuthorized(address serviceProvider) { + if (!GRAPH_STAKING.isAuthorized(msg.sender, serviceProvider, address(this))) { + revert ProvisionManagerNotAuthorized(msg.sender, serviceProvider, address(this)); + } + _; + } + + constructor() { + minimumProvisionTokens = type(uint256).min; + maximumProvisionTokens = type(uint256).max; + + minimumThawingPeriod = type(uint64).min; + maximumThawingPeriod = type(uint64).max; + + minimumVerifierCut = type(uint32).min; + maximumVerifierCut = type(uint32).max; + } + + function _checkAndAcceptProvision(address _serviceProvider) internal virtual { + _checkProvisionParameters(_serviceProvider); + GRAPH_STAKING.acceptProvision(_serviceProvider); + } + + // -- Provision Parameters: setters -- + function _setProvisionTokensRange(uint256 _min, uint256 _max) internal { + minimumProvisionTokens = _min; + maximumProvisionTokens = _max; + } + + function _setVerifierCutRange(uint32 _min, uint32 _max) internal { + minimumVerifierCut = _min; + maximumVerifierCut = _max; + } + + function _setThawingPeriodRange(uint64 _min, uint64 _max) internal { + minimumThawingPeriod = _min; + maximumThawingPeriod = _max; + } + + /// @notice Checks if the service provider has a valid provision for the data service in the staking contract + /// @param _serviceProvider The address of the service provider + function _checkProvisionParameters(address _serviceProvider) internal view virtual { + IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); + + (uint256 provisionTokensMin, uint256 provisionTokensMax) = _getProvisionTokensRange(); + if (!provision.tokens.isInRange(provisionTokensMin, provisionTokensMax)) { + revert ProvisionManagerInvalidProvisionTokens(provision.tokens, provisionTokensMin, provisionTokensMax); + } + + (uint64 thawingPeriodMin, uint64 thawingPeriodMax) = _getThawingPeriodRange(); + if (!uint256(provision.thawingPeriod).isInRange(thawingPeriodMin, thawingPeriodMax)) { + revert ProvisionManagerInvalidThawingPeriod(provision.thawingPeriod, thawingPeriodMin, thawingPeriodMax); + } + + (uint32 verifierCutMin, uint32 verifierCutMax) = _getVerifierCutRange(); + if (!uint256(provision.maxVerifierCut).isInRange(verifierCutMin, verifierCutMax)) { + revert ProvisionManagerInvalidVerifierCut(provision.maxVerifierCut, verifierCutMin, verifierCutMax); + } + } + + // -- Provision Parameters: getters -- + function _getProvisionTokensRange() internal view virtual returns (uint256 min, uint256 max) { + return (minimumProvisionTokens, maximumProvisionTokens); + } + + function _getThawingPeriodRange() internal view virtual returns (uint64 min, uint64 max) { + return (minimumThawingPeriod, maximumThawingPeriod); + } + + function _getVerifierCutRange() internal view virtual returns (uint32 min, uint32 max) { + return (minimumVerifierCut, maximumVerifierCut); + } + + function _getProvision(address _serviceProvider) internal view returns (IHorizonStaking.Provision memory) { + return GRAPH_STAKING.get(_serviceProvider); + } +} diff --git a/packages/subgraph-service/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/subgraph-service/contracts/data-service/utilities/ProvisionManagerStorage.sol new file mode 100644 index 000000000..e7a25e6ab --- /dev/null +++ b/packages/subgraph-service/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +abstract contract ProvisionManagerV1Storage { + /// @notice The minimum amount of tokens required to register a provision in the data service + uint256 public minimumProvisionTokens; + + /// @notice The maximum amount of tokens allowed to register a provision in the data service + uint256 public maximumProvisionTokens; + + /// @notice The minimum thawing period required to register a provision in the data service + uint64 public minimumThawingPeriod; + + /// @notice The maximum thawing period allowed to register a provision in the data service + uint64 public maximumThawingPeriod; + + /// @notice The minimum verifier cut required to register a provision in the data service + uint32 public minimumVerifierCut; + + /// @notice The maximum verifier cut allowed to register a provision in the data service + uint32 public maximumVerifierCut; + + /// @dev Gap to allow adding variables in future upgrades + uint256[50] private __gap; +} diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol new file mode 100644 index 000000000..d40750a55 --- /dev/null +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity ^0.8.24; +pragma abicoder v2; + +import { Attestation } from "../libraries/Attestation.sol"; + +interface IDisputeManager { + // -- Dispute -- + + enum DisputeType { + Null, + IndexingDispute, + QueryDispute + } + + enum DisputeStatus { + Null, + Accepted, + Rejected, + Drawn, + Pending, + Cancelled + } + + // Disputes contain info necessary for the Arbitrator to verify and resolve + struct Dispute { + address indexer; + address fisherman; + uint256 deposit; + bytes32 relatedDisputeId; + DisputeType disputeType; + DisputeStatus status; + uint256 createdAt; + } + + // -- Attestation -- + + // -- Configuration -- + + function setDisputePeriod(uint64 disputePeriod) external; + + function setArbitrator(address arbitrator) external; + + function setMinimumDeposit(uint256 minimumDeposit) external; + + function setFishermanRewardPercentage(uint32 percentage) external; + + function setMaxSlashingPercentage(uint32 maxPercentage) external; + + // -- Dispute -- + + function createQueryDispute(bytes calldata attestationData, uint256 deposit) external returns (bytes32); + + function createQueryDisputeConflict( + bytes calldata attestationData1, + bytes calldata attestationData2 + ) external returns (bytes32, bytes32); + + function createIndexingDispute(address allocationId, uint256 deposit) external returns (bytes32); + + function acceptDispute(bytes32 disputeId, uint256 slashAmount) external; + + function rejectDispute(bytes32 disputeId) external; + + function drawDispute(bytes32 disputeId) external; + + function cancelDispute(bytes32 disputeId) external; + + // -- Getters -- + + function getVerifierCut() external view returns (uint32); + + function getDisputePeriod() external view returns (uint64); + + function isDisputeCreated(bytes32 disputeId) external view returns (bool); + + function encodeReceipt(Attestation.Receipt memory receipt) external view returns (bytes32); + + function getAttestationIndexer(Attestation.State memory attestation) external view returns (address); + + function areConflictingAttestations( + Attestation.State memory attestation1, + Attestation.State memory attestation2 + ) external pure returns (bool); +} diff --git a/packages/subgraph-service/contracts/interfaces/IGraphEscrow.sol b/packages/subgraph-service/contracts/interfaces/IGraphEscrow.sol new file mode 100644 index 000000000..111d667b2 --- /dev/null +++ b/packages/subgraph-service/contracts/interfaces/IGraphEscrow.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +interface IGraphEscrow { + function getSender(address signer) external view returns (address sender); +} diff --git a/packages/subgraph-service/contracts/interfaces/IGraphPayments.sol b/packages/subgraph-service/contracts/interfaces/IGraphPayments.sol new file mode 100644 index 000000000..0fa08fa63 --- /dev/null +++ b/packages/subgraph-service/contracts/interfaces/IGraphPayments.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +interface IGraphPayments { + enum PaymentTypes { + QueryFee, + IndexingFee + } + + function collect( + address sender, + address receiver, + uint256 tokens, + PaymentTypes paymentType, + uint256 tokensDataService + ) external returns (uint256); +} diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol new file mode 100644 index 000000000..ab62a3d84 --- /dev/null +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IDataServiceFees } from "../data-service/extensions/IDataServiceFees.sol"; + +import { Allocation } from "../libraries/Allocation.sol"; +import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; + +interface ISubgraphService is IDataServiceFees { + struct Indexer { + uint256 registeredAt; + string url; + string geoHash; + } + + struct PaymentFee { + uint128 servicePercentage; + uint128 curationPercentage; + } + + function resizeAllocation(address indexer, address allocationId, uint256 tokens) external; + + function migrateLegacyAllocation(address indexer, address allocationId, bytes32 subgraphDeploymentID) external; + + function setPauseGuardian(address pauseGuardian, bool allowed) external; + + function getAllocation(address allocationId) external view returns (Allocation.State memory); + + function getLegacyAllocation(address allocationId) external view returns (LegacyAllocation.State memory); + + function encodeAllocationProof(address _indexer, address _allocationId) external view returns (bytes32); +} diff --git a/packages/subgraph-service/contracts/interfaces/ITAPVerifier.sol b/packages/subgraph-service/contracts/interfaces/ITAPVerifier.sol new file mode 100644 index 000000000..2cbfdf052 --- /dev/null +++ b/packages/subgraph-service/contracts/interfaces/ITAPVerifier.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +interface ITAPVerifier { + struct ReceiptAggregateVoucher { + address dataService; + address serviceProvider; + uint64 timestampNs; + uint128 valueAggregate; + bytes metadata; + } + + struct SignedRAV { + ReceiptAggregateVoucher rav; + bytes signature; // 65 bytes: r (32 Bytes) || s (32 Bytes) || v (1 Byte) + } + + struct SenderAuthorization { + address sender; // Sender the signer is authorized to sign for + uint256 thawEndTimestamp; // Timestamp at which thawing period ends (zero if not thawing) + } + + function verify(SignedRAV calldata rav) external returns (address sender); +} diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol new file mode 100644 index 000000000..f6e9e0000 --- /dev/null +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +library Allocation { + using Allocation for State; + + struct State { + address indexer; + bytes32 subgraphDeploymentId; + uint256 tokens; + uint256 createdAt; + uint256 closedAt; + uint256 lastPOIPresentedAt; + uint256 accRewardsPerAllocatedToken; + uint256 accRewardsPending; + } + + error AllocationAlreadyExists(address allocationId); + error AllocationDoesNotExist(address allocationId); + error AllocationClosed(address allocationId, uint256 closedAt); + error AllocationZeroTokens(address allocationId); + + function create( + mapping(address => State) storage self, + address indexer, + address allocationId, + bytes32 subgraphDeploymentId, + uint256 tokens, + uint256 accRewardsPerAllocatedToken + ) internal returns (State memory) { + if (self[allocationId].exists()) revert AllocationAlreadyExists(allocationId); + + State memory allocation = State({ + indexer: indexer, + subgraphDeploymentId: subgraphDeploymentId, + tokens: tokens, + createdAt: block.timestamp, + closedAt: 0, + lastPOIPresentedAt: block.timestamp, + accRewardsPerAllocatedToken: accRewardsPerAllocatedToken, + accRewardsPending: 0 + }); + + self[allocationId] = allocation; + + return allocation; + } + + // Update POI timestamp and take rewards snapshot + // For stale POIs this ensures the rewards are not collected with the next valid POI + function presentPOI(mapping(address => State) storage self, address allocationId) internal returns (State memory) { + State storage allocation = _get(self, allocationId); + if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); + if (allocation.isAltruistic()) revert AllocationZeroTokens(allocationId); + allocation.lastPOIPresentedAt = block.timestamp; + + return allocation; + } + + function snapshotRewards( + mapping(address => State) storage self, + address allocationId, + uint256 accRewardsPerAllocatedToken + ) internal returns (State memory) { + State storage allocation = _get(self, allocationId); + if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); + allocation.accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; + + return allocation; + } + + function close(mapping(address => State) storage self, address allocationId) internal returns (State memory) { + State storage allocation = _get(self, allocationId); + if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); + allocation.closedAt = block.timestamp; + + return allocation; + } + + function get(mapping(address => State) storage self, address allocationId) internal view returns (State memory) { + return _get(self, allocationId); + } + + function exists(State memory self) internal pure returns (bool) { + return self.createdAt != 0; + } + + function isOpen(State memory self) internal pure returns (bool) { + return self.exists() && self.closedAt == 0; + } + + function isAltruistic(State memory self) internal pure returns (bool) { + return self.exists() && self.tokens == 0; + } + + function _get(mapping(address => State) storage self, address allocationId) private view returns (State storage) { + State storage allocation = self[allocationId]; + if (!allocation.exists()) revert AllocationDoesNotExist(allocationId); + return allocation; + } +} diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol new file mode 100644 index 000000000..1ff99b0e3 --- /dev/null +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +library Attestation { + // Receipt content sent from the service provider in response to request + struct Receipt { + bytes32 requestCID; + bytes32 responseCID; + bytes32 subgraphDeploymentId; + } + + // Attestation sent from the service provider in response to a request + struct State { + bytes32 requestCID; + bytes32 responseCID; + bytes32 subgraphDeploymentId; + bytes32 r; + bytes32 s; + uint8 v; + } + + // Attestation size is the sum of the receipt (96) + signature (65) + uint256 private constant ATTESTATION_SIZE_BYTES = RECEIPT_SIZE_BYTES + SIG_SIZE_BYTES; + uint256 private constant RECEIPT_SIZE_BYTES = 96; + + uint256 private constant SIG_R_LENGTH = 32; + uint256 private constant SIG_S_LENGTH = 32; + uint256 private constant SIG_V_LENGTH = 1; + uint256 private constant SIG_R_OFFSET = RECEIPT_SIZE_BYTES; + uint256 private constant SIG_S_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH; + uint256 private constant SIG_V_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH + SIG_S_LENGTH; + uint256 private constant SIG_SIZE_BYTES = SIG_R_LENGTH + SIG_S_LENGTH + SIG_V_LENGTH; + + uint256 private constant UINT8_BYTE_LENGTH = 1; + uint256 private constant BYTES32_BYTE_LENGTH = 32; + + error AttestationInvalidBytesLength(uint256 length, uint256 expectedLength); + + /** + * @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 + */ + function areConflicting( + Attestation.State memory _attestation1, + Attestation.State memory _attestation2 + ) internal pure returns (bool) { + return (_attestation1.requestCID == _attestation2.requestCID && + _attestation1.subgraphDeploymentId == _attestation2.subgraphDeploymentId && + _attestation1.responseCID != _attestation2.responseCID); + } + + /** + * @dev Parse the bytes attestation into a struct from `_data`. + * @return Attestation struct + */ + function parse(bytes memory _data) internal pure returns (State memory) { + // Check attestation data length + if (_data.length != ATTESTATION_SIZE_BYTES) { + revert AttestationInvalidBytesLength(_data.length, ATTESTATION_SIZE_BYTES); + } + + // Decode receipt + (bytes32 requestCID, bytes32 responseCID, bytes32 subgraphDeploymentId) = abi.decode( + _data, + (bytes32, bytes32, bytes32) + ); + + // Decode signature + // Signature is expected to be in the order defined in the Attestation struct + bytes32 r = _toBytes32(_data, SIG_R_OFFSET); + bytes32 s = _toBytes32(_data, SIG_S_OFFSET); + uint8 v = _toUint8(_data, SIG_V_OFFSET); + + return State(requestCID, responseCID, subgraphDeploymentId, r, s, v); + } + + /** + * @dev Parse a uint8 from `_bytes` starting at offset `_start`. + * @return uint8 value + */ + function _toUint8(bytes memory _bytes, uint256 _start) private pure returns (uint8) { + if (_bytes.length < (_start + UINT8_BYTE_LENGTH)) { + revert AttestationInvalidBytesLength(_bytes.length, _start + UINT8_BYTE_LENGTH); + } + uint8 tempUint; + + // solhint-disable-next-line no-inline-assembly + assembly { + tempUint := mload(add(add(_bytes, 0x1), _start)) + } + + return tempUint; + } + + /** + * @dev Parse a bytes32 from `_bytes` starting at offset `_start`. + * @return bytes32 value + */ + function _toBytes32(bytes memory _bytes, uint256 _start) private pure returns (bytes32) { + if (_bytes.length < (_start + BYTES32_BYTE_LENGTH)) { + revert AttestationInvalidBytesLength(_bytes.length, _start + BYTES32_BYTE_LENGTH); + } + bytes32 tempBytes32; + + // solhint-disable-next-line no-inline-assembly + assembly { + tempBytes32 := mload(add(add(_bytes, 0x20), _start)) + } + + return tempBytes32; + } +} diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol new file mode 100644 index 000000000..bef060e8b --- /dev/null +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +library LegacyAllocation { + using LegacyAllocation for State; + + struct State { + address indexer; + bytes32 subgraphDeploymentID; + } + + error LegacyAllocationExists(address allocationId); + error LegacyAllocationDoesNotExist(address allocationId); + error LegacyAllocationAlreadyMigrated(address allocationId); + + function migrate( + mapping(address => State) storage self, + address indexer, + address allocationId, + bytes32 subgraphDeploymentID + ) internal { + if (self[allocationId].exists()) revert LegacyAllocationAlreadyMigrated(allocationId); + + State memory allocation = State({ indexer: indexer, subgraphDeploymentID: subgraphDeploymentID }); + + self[allocationId] = allocation; + } + + function get(mapping(address => State) storage self, address allocationId) internal view returns (State memory) { + return _get(self, allocationId); + } + + function revertIfExists(mapping(address => State) storage self, address allocationId) internal view { + if (self[allocationId].exists()) revert LegacyAllocationExists(allocationId); + } + + function exists(State memory self) internal pure returns (bool) { + return self.indexer != address(0); + } + + function _get(mapping(address => State) storage self, address allocationId) private view returns (State storage) { + State storage allocation = self[allocationId]; + if (!allocation.exists()) revert LegacyAllocationDoesNotExist(allocationId); + return allocation; + } +} diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol new file mode 100644 index 000000000..bcd7f1097 --- /dev/null +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; + +import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; +import { Allocation } from "../libraries/Allocation.sol"; +import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; +import { PPMMath } from "../data-service/libraries/PPMMath.sol"; +import { ProvisionTracker } from "../data-service/libraries/ProvisionTracker.sol"; + +abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManagerV1Storage { + using ProvisionTracker for mapping(address => uint256); + using Allocation for mapping(address => Allocation.State); + using LegacyAllocation for mapping(address => LegacyAllocation.State); + using PPMMath for uint256; + + // -- Immutables -- + bytes32 private immutable EIP712_ALLOCATION_PROOF_TYPEHASH = + keccak256("AllocationIdProof(address indexer,address allocationId)"); + + /** + * @dev Emitted when `indexer` allocated `tokens` amount to `subgraphDeploymentId` + * during `epoch`. + * `allocationId` indexer derived address used to identify the allocation. + */ + event AllocationCreated( + address indexed indexer, + address indexed allocationId, + bytes32 indexed subgraphDeploymentId, + uint256 tokens + ); + + event AllocationCollected( + address indexed indexer, + address indexed allocationId, + bytes32 indexed subgraphDeploymentId, + uint256 tokensRewards, + uint256 tokensIndexerRewards, + uint256 tokensDelegationRewards, + bytes32 poi + ); + + event AllocationResized( + address indexed indexer, + address indexed allocationId, + bytes32 indexed subgraphDeploymentId, + uint256 newTokens, + uint256 oldTokens + ); + + /** + * @dev Emitted when `indexer` closes an allocation with id `allocationId`. + * An amount of `tokens` get unallocated from `subgraphDeploymentId`. + */ + event AllocationClosed( + address indexed indexer, + address indexed allocationId, + bytes32 indexed subgraphDeploymentId, + uint256 tokens + ); + + event LegacyAllocationMigrated( + address indexed indexer, + address indexed allocationId, + bytes32 indexed subgraphDeploymentId + ); + + error AllocationManagerInvalidAllocationProof(address signer, address allocationId); + error AllocationManagerInvalidAllocationId(); + error AllocationManagerZeroTokensAllocation(address allocationId); + error AllocationManagerAllocationClosed(address allocationId); + error AllocationManagerAllocationSameSize(address allocationId, uint256 tokens); + error AllocationManagerInvalidZeroPOI(); + + constructor(string memory name, string memory version) EIP712(name, version) {} + + function _migrateLegacyAllocation(address _indexer, address _allocationId, bytes32 _subgraphDeploymentId) internal { + legacyAllocations.migrate(_indexer, _allocationId, _subgraphDeploymentId); + emit LegacyAllocationMigrated(_indexer, _allocationId, _subgraphDeploymentId); + } + + function _allocate( + address _indexer, + address _allocationId, + bytes32 _subgraphDeploymentId, + uint256 _tokens, + bytes memory _allocationProof + ) internal returns (Allocation.State memory) { + if (_allocationId == address(0)) revert AllocationManagerInvalidAllocationId(); + + _verifyAllocationProof(_indexer, _allocationId, _allocationProof); + + // Ensure allocation id is not reused + // need to check both subgraph service (on create()) and legacy allocations + legacyAllocations.revertIfExists(_allocationId); + Allocation.State memory allocation = allocations.create( + _indexer, + _allocationId, + _subgraphDeploymentId, + _tokens, + // allos can be resized now, so we need to always take snapshot + GRAPH_REWARDS_MANAGER.onSubgraphAllocationUpdate(_subgraphDeploymentId) + ); + + // Check that the indexer has enough tokens available + allocationProvisionTracker.lock(GRAPH_STAKING, _indexer, _tokens); + + // Update total allocated tokens for the subgraph deployment + subgraphAllocatedTokens[allocation.subgraphDeploymentId] = + subgraphAllocatedTokens[allocation.subgraphDeploymentId] + + allocation.tokens; + + emit AllocationCreated(_indexer, _allocationId, _subgraphDeploymentId, allocation.tokens); + return allocation; + } + + // Update POI timestamp and take rewards snapshot even for 0 rewards + // This ensures the rewards are actually skipped and not collected with the next valid POI + function _collectPOIRewards(address _allocationId, bytes32 _poi) internal returns (uint256) { + if (_poi == bytes32(0)) revert AllocationManagerInvalidZeroPOI(); + + Allocation.State memory allocation = allocations.get(_allocationId); + + // Mint indexing rewards, stale POIs get no rewards... + uint256 timeSinceLastPOI = block.number - allocation.lastPOIPresentedAt; + uint256 tokensRewards = timeSinceLastPOI <= maxPOIStaleness + ? GRAPH_REWARDS_MANAGER.takeRewards(_allocationId) + : 0; + + // ... but we still take a snapshot to ensure the rewards are not collected with the next valid POI + allocations.snapshotRewards( + _allocationId, + GRAPH_REWARDS_MANAGER.onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) + ); + allocations.presentPOI(_allocationId); + + if (tokensRewards == 0) { + emit AllocationCollected(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, 0, 0, 0, _poi); + return tokensRewards; + } + + // Distribute rewards to delegators + // TODO: remove the uint8 cast when PRs are merged + uint256 delegatorCut = GRAPH_STAKING.getDelegationCut( + allocation.indexer, + uint8(IGraphPayments.PaymentTypes.IndexingFee) + ); + uint256 tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); + GRAPH_TOKEN.approve(address(GRAPH_STAKING), tokensDelegationRewards); + GRAPH_STAKING.addToDelegationPool(allocation.indexer, tokensDelegationRewards); + + // Distribute rewards to indexer + uint256 tokensIndexerRewards = tokensRewards - tokensDelegationRewards; + address rewardsDestination = rewardsDestination[allocation.indexer]; + if (rewardsDestination == address(0)) { + GRAPH_TOKEN.approve(address(GRAPH_STAKING), tokensIndexerRewards); + GRAPH_STAKING.stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); + } else { + GRAPH_TOKEN.transfer(rewardsDestination, tokensIndexerRewards); + } + + emit AllocationCollected( + allocation.indexer, + _allocationId, + allocation.subgraphDeploymentId, + tokensRewards, + tokensIndexerRewards, + tokensDelegationRewards, + _poi + ); + + return tokensRewards; + } + + function _resizeAllocation(address _allocationId, uint256 _tokens) internal returns (Allocation.State memory) { + Allocation.State memory allocation = allocations.get(_allocationId); + + // Exit early if the allocation size is the same + if (_tokens == allocation.tokens) { + revert AllocationManagerAllocationSameSize(_allocationId, _tokens); + } + + // Update provision tracker + uint256 oldTokens = allocation.tokens; + if (_tokens > oldTokens) { + allocationProvisionTracker.lock(GRAPH_STAKING, allocation.indexer, _tokens - oldTokens); + } else { + allocationProvisionTracker.release(allocation.indexer, oldTokens - _tokens); + } + + // Calculate rewards that have been accrued since the last snapshot but not yet issued + uint256 accRewardsPerAllocatedToken = GRAPH_REWARDS_MANAGER.onSubgraphAllocationUpdate( + allocation.subgraphDeploymentId + ); + uint256 accRewardsPending = accRewardsPerAllocatedToken - allocation.accRewardsPerAllocatedToken; + + // Update the allocation + allocations[_allocationId].tokens = _tokens; + allocations[_allocationId].accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; + allocations[_allocationId].accRewardsPending = allocations[_allocationId].accRewardsPending + accRewardsPending; + + // Update total allocated tokens for the subgraph deployment + subgraphAllocatedTokens[allocation.subgraphDeploymentId] = + subgraphAllocatedTokens[allocation.subgraphDeploymentId] + + (_tokens - oldTokens); + + emit AllocationResized(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, _tokens, oldTokens); + return allocations[_allocationId]; + } + + function _closeAllocation(address _allocationId) internal returns (Allocation.State memory) { + Allocation.State memory allocation = allocations.get(_allocationId); + + allocations.close(_allocationId); + allocationProvisionTracker.release(allocation.indexer, allocation.tokens); + + subgraphAllocatedTokens[allocation.subgraphDeploymentId] = + subgraphAllocatedTokens[allocation.subgraphDeploymentId] - + allocation.tokens; + + emit AllocationClosed(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, allocation.tokens); + return allocations[_allocationId]; + } + + function _getAllocation(address _allocationId) internal view returns (Allocation.State memory) { + return allocations.get(_allocationId); + } + + function _getLegacyAllocation(address _allocationId) internal view returns (LegacyAllocation.State memory) { + return legacyAllocations.get(_allocationId); + } + + // -- Allocation Proof Verification -- + // Caller must prove that they own the private key for the allocationId address + // The proof is an EIP712 signed message of (indexer,allocationId) + function _verifyAllocationProof(address _indexer, address _allocationId, bytes memory _proof) internal view { + bytes32 digest = _encodeAllocationProof(_indexer, _allocationId); + address signer = ECDSA.recover(digest, _proof); + if (signer != _allocationId) revert AllocationManagerInvalidAllocationProof(signer, _allocationId); + } + + function _encodeAllocationProof(address _indexer, address _allocationId) internal view returns (bytes32) { + return + EIP712._hashTypedDataV4(keccak256(abi.encode(EIP712_ALLOCATION_PROOF_TYPEHASH, _indexer, _allocationId))); + } +} diff --git a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol new file mode 100644 index 000000000..c737acabf --- /dev/null +++ b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { Allocation } from "../libraries/Allocation.sol"; +import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; + +abstract contract AllocationManagerV1Storage { + mapping(address allocationId => Allocation.State allocation) public allocations; + mapping(address indexer => uint256 tokens) public allocationProvisionTracker; + mapping(address allocationId => LegacyAllocation.State allocation) public legacyAllocations; + + /// @notice Maximum amount of since last POI was presented to qualify for indexing rewards + uint256 public maxPOIStaleness; + + /// @dev Destination of accrued rewards + mapping(address indexer => address destination) public rewardsDestination; + + /// @notice Track total tokens allocated per subgraph deployment + /// @dev Used to calculate indexing rewards + mapping(bytes32 subgraphDeploymentId => uint256 tokens) public subgraphAllocatedTokens; + + /// @dev Gap to allow adding variables in future upgrades + uint256[50] private __gap; +} diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol new file mode 100644 index 000000000..2c1e18150 --- /dev/null +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { AttestationManagerV1Storage } from "./AttestationManagerStorage.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { Attestation } from "../libraries/Attestation.sol"; + +abstract contract AttestationManager is AttestationManagerV1Storage { + bytes32 private constant RECEIPT_TYPE_HASH = + keccak256("Receipt(bytes32 requestCID,bytes32 responseCID,bytes32 subgraphDeploymentID)"); + + bytes32 private constant DOMAIN_TYPE_HASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); + bytes32 private constant DOMAIN_NAME_HASH = keccak256("Graph Protocol"); + bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); + bytes32 private constant DOMAIN_SALT = 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; + + constructor() { + // EIP-712 domain separator + _domainSeparator = keccak256( + abi.encode( + DOMAIN_TYPE_HASH, + DOMAIN_NAME_HASH, + DOMAIN_VERSION_HASH, + block.chainid, + address(this), + DOMAIN_SALT + ) + ); + } + + /** + * @dev Recover the signer address of the `_attestation`. + * @param _attestation The attestation struct + * @return Signer address + */ + function _recoverSigner(Attestation.State memory _attestation) internal view returns (address) { + // Obtain the hash of the fully-encoded message, per EIP-712 encoding + Attestation.Receipt memory receipt = Attestation.Receipt( + _attestation.requestCID, + _attestation.responseCID, + _attestation.subgraphDeploymentId + ); + bytes32 messageHash = _encodeReceipt(receipt); + + // Obtain the signer of the fully-encoded EIP-712 message hash + // NOTE: The signer of the attestation is the indexer that served the request + return ECDSA.recover(messageHash, abi.encodePacked(_attestation.r, _attestation.s, _attestation.v)); + } + + /** + * @dev Get the message hash that a indexer used to sign the receipt. + * 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 _encodeReceipt(Attestation.Receipt memory _receipt) internal view returns (bytes32) { + return + keccak256( + abi.encodePacked( + "\x19\x01", // EIP-191 encoding pad, EIP-712 version 1 + _domainSeparator, + keccak256( + abi.encode( + RECEIPT_TYPE_HASH, + _receipt.requestCID, + _receipt.responseCID, + _receipt.subgraphDeploymentId + ) // EIP 712-encoded message hash + ) + ) + ); + } +} diff --git a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol new file mode 100644 index 000000000..80aa0388f --- /dev/null +++ b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +abstract contract AttestationManagerV1Storage { + bytes32 internal _domainSeparator; + + /// @dev Gap to allow adding variables in future upgrades + uint256[50] private __gap; +} diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol new file mode 100644 index 000000000..cd87de102 --- /dev/null +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { ITAPVerifier } from "../interfaces/ITAPVerifier.sol"; +import { IDisputeManager } from "../interfaces/IDisputeManager.sol"; +import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; +import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; + +abstract contract Directory { + ITAPVerifier public immutable TAP_VERIFIER; + IDisputeManager public immutable DISPUTE_MANAGER; + ISubgraphService public immutable SUBGRAPH_SERVICE; + ICuration public immutable CURATION; + + event SubgraphServiceDirectoryInitialized( + address subgraphService, + address tapVerifier, + address disputeManager, + address curation + ); + error DirectoryNotDisputeManager(address caller, address disputeManager); + + modifier onlyDisputeManager() { + if (msg.sender != address(DISPUTE_MANAGER)) { + revert DirectoryNotDisputeManager(msg.sender, address(DISPUTE_MANAGER)); + } + _; + } + + constructor(address subgraphService, address tapVerifier, address disputeManager, address curation) { + SUBGRAPH_SERVICE = ISubgraphService(subgraphService); + TAP_VERIFIER = ITAPVerifier(tapVerifier); + DISPUTE_MANAGER = IDisputeManager(disputeManager); + CURATION = ICuration(curation); + + emit SubgraphServiceDirectoryInitialized(subgraphService, tapVerifier, disputeManager, curation); + } +} diff --git a/packages/subgraph-service/eslint.config.js b/packages/subgraph-service/eslint.config.js new file mode 100644 index 000000000..2cb4335fd --- /dev/null +++ b/packages/subgraph-service/eslint.config.js @@ -0,0 +1,21 @@ +// @ts-check +/* eslint-disable no-undef */ +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ + +const eslintGraphConfig = require('eslint-graph-config') +module.exports = [ + ...eslintGraphConfig.default, + { + rules: { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + }, + }, + { + ignores: ['typechain-types/*'], + }, +] diff --git a/packages/subgraph-service/foundry.toml b/packages/subgraph-service/foundry.toml new file mode 100644 index 000000000..55f7ffd31 --- /dev/null +++ b/packages/subgraph-service/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = 'contracts' +out = 'build' +libs = ['node_modules', 'lib'] +test = 'test' +cache_path = 'cache_forge' \ No newline at end of file diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts new file mode 100644 index 000000000..f4a7067b7 --- /dev/null +++ b/packages/subgraph-service/hardhat.config.ts @@ -0,0 +1,37 @@ +// import '@nomicfoundation/hardhat-foundry' +import '@nomicfoundation/hardhat-toolbox' +import 'hardhat-contract-sizer' +import 'hardhat-storage-layout' +import 'solidity-docgen' + +import { HardhatUserConfig } from 'hardhat/config' + +const config: HardhatUserConfig = { + solidity: { + compilers: [ + { + version: '0.8.24', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + metadata: { + useLiteralContent: true, + }, + outputSelection: { + '*': { + '*': ['storageLayout', 'metadata'], + }, + }, + }, + }, + ], + }, + paths: { + artifacts: './build/contracts', + sources: './contracts', + }, +} + +export default config diff --git a/packages/subgraph-service/lib/forge-std b/packages/subgraph-service/lib/forge-std new file mode 160000 index 000000000..bb4ceea94 --- /dev/null +++ b/packages/subgraph-service/lib/forge-std @@ -0,0 +1 @@ +Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json new file mode 100644 index 000000000..f66d229de --- /dev/null +++ b/packages/subgraph-service/package.json @@ -0,0 +1,63 @@ +{ + "name": "@graphprotocol/subgraph-service", + "version": "0.0.1", + "description": "", + "author": "The Graph Team", + "license": "GPL-2.0-or-later", + "scripts": { + "lint:ts": "eslint '**/*.{js,ts}' --fix", + "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", + "lint": "yarn lint:ts && yarn lint:sol", + "clean": "rm -rf build cache typechain-types", + "build": "forge build && hardhat compile", + "test": "forge test && hardhat test" + }, + "devDependencies": { + "@graphprotocol/contracts": "workspace:^7.0.0", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-foundry": "^1.1.1", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-toolbox": "^4.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@openzeppelin/contracts": "^5.0.2", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=16.0.0", + "chai": "^4.2.0", + "eslint": "^8.56.0", + "eslint-graph-config": "workspace:^0.0.1", + "ethers": "^6.4.0", + "hardhat": "^2.20.1", + "hardhat-contract-sizer": "^2.10.0", + "hardhat-gas-reporter": "^1.0.8", + "hardhat-storage-layout": "^0.1.7", + "lint-staged": "^15.2.2", + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1", + "solhint": "^4.5.4", + "solhint-graph-config": "workspace:^0.0.1", + "solhint-plugin-graph": "file:node_modules/solhint-graph-config/plugin", + "solidity-coverage": "^0.8.0", + "solidity-docgen": "^0.6.0-beta.36", + "ts-node": ">=8.0.0", + "typechain": "^8.3.0", + "typescript": "^5.3.3" + }, + "lint-staged": { + "contracts/**/*.sol": [ + "yarn lint:sol" + ], + "**/*.ts": [ + "yarn lint:ts" + ], + "**/*.js": [ + "yarn lint:ts" + ], + "**/*.json": [ + "yarn lint:ts" + ] + } +} diff --git a/packages/subgraph-service/prettier.config.js b/packages/subgraph-service/prettier.config.js new file mode 100644 index 000000000..5b8e866f2 --- /dev/null +++ b/packages/subgraph-service/prettier.config.js @@ -0,0 +1,2 @@ +const prettierGraphConfig = require('solhint-graph-config/prettier') +module.exports = prettierGraphConfig diff --git a/packages/subgraph-service/remappings.txt b/packages/subgraph-service/remappings.txt new file mode 100644 index 000000000..1bd6482cd --- /dev/null +++ b/packages/subgraph-service/remappings.txt @@ -0,0 +1,5 @@ +@graphprotocol/contracts/=node_modules/@graphprotocol/contracts/ +forge-std/=lib/forge-std/src/ +ds-test/=lib/forge-std/lib/ds-test/src/ +eth-gas-reporter/=node_modules/eth-gas-reporter/ +hardhat/=node_modules/hardhat/ diff --git a/packages/subgraph-service/scripts/deploy.ts b/packages/subgraph-service/scripts/deploy.ts new file mode 100644 index 000000000..cf87ff10f --- /dev/null +++ b/packages/subgraph-service/scripts/deploy.ts @@ -0,0 +1,28 @@ +import { ethers } from 'hardhat' + +async function main() { + const currentTimestampInSeconds = Math.round(Date.now() / 1000) + const unlockTime = currentTimestampInSeconds + 60 + + const lockedAmount = ethers.parseEther('0.001') + const a = 1 + console.log(a) + const lock = await ethers.deployContract('Lock', [unlockTime], { + value: lockedAmount, + }) + + await lock.waitForDeployment() + + console.log( + `Lock with ${ethers.formatEther( + lockedAmount, + )}ETH and unlock timestamp ${unlockTime} deployed to ${typeof lock.target == 'string' ? lock.target : ''}`, + ) +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error) + process.exitCode = 1 +}) diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol new file mode 100644 index 000000000..bc8e8f42d --- /dev/null +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -0,0 +1,501 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; +import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; + +import { DisputeManager } from "../contracts/DisputeManager.sol"; +import { IDisputeManager } from "../contracts/interfaces/IDisputeManager.sol"; +import { Attestation } from "../contracts/libraries/Attestation.sol"; + +import { SubgraphService } from "../contracts/SubgraphService.sol"; + +// Mocks + +import "./mocks/MockGRTToken.sol"; +import "./mocks/MockHorizonStaking.sol"; +import "./mocks/MockRewardsManager.sol"; + +contract DisputeManagerTest is Test { + DisputeManager disputeManager; + + address governor; + address arbitrator; + + uint256 indexerPrivateKey; + address indexer; + + uint256 fishermanPrivateKey; + address fisherman; + + uint256 allocationIDPrivateKey; + address allocationID; + + uint64 disputePeriod = 300; // 5 minutes + uint256 minimumDeposit = 100 ether; // 100 GRT + uint32 fishermanRewardPercentage = 100000; // 10% + uint32 maxSlashingPercentage = 500000; // 50% + + Controller controller; + MockGRTToken graphToken; + SubgraphService subgraphService; + MockHorizonStaking staking; + MockRewardsManager rewardsManager; + + // Setup + + function setUp() public { + governor = address(0xA1); + arbitrator = address(0xA2); + + indexerPrivateKey = 0xB1; + indexer = vm.addr(indexerPrivateKey); + + fishermanPrivateKey = 0xC1; + fisherman = vm.addr(fishermanPrivateKey); + + allocationIDPrivateKey = 0xD1; + allocationID = vm.addr(allocationIDPrivateKey); + + graphToken = new MockGRTToken(); + staking = new MockHorizonStaking(address(graphToken)); + rewardsManager = new MockRewardsManager(); + + address payments = address(0xE2); + address tapVerifier = address(0xE3); + address curation = address(0xE4); + + vm.startPrank(governor); + controller = new Controller(); + controller.setContractProxy(keccak256("GraphToken"), address(graphToken)); + controller.setContractProxy(keccak256("Staking"), address(staking)); + controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); + vm.stopPrank(); + + disputeManager = new DisputeManager( + address(controller), + arbitrator, + disputePeriod, + minimumDeposit, + fishermanRewardPercentage, + maxSlashingPercentage + ); + + subgraphService = new SubgraphService( + address(controller), + address(disputeManager), + tapVerifier, + curation, + 1000 ether + ); + + disputeManager.setSubgraphService(address(subgraphService)); + } + + // Helper functions + + function createProvisionAndAllocate(address _allocationID, uint256 tokens) private { + vm.startPrank(indexer); + graphToken.mint(indexer, tokens); + staking.provision(tokens, address(subgraphService), 500000, 300); + bytes32 subgraphDeployment = keccak256(abi.encodePacked("Subgraph Deployment ID")); + bytes32 digest = subgraphService.encodeAllocationProof(indexer, _allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + + subgraphService.register( + indexer, + abi.encode("url", "geoHash") + ); + + bytes memory data = abi.encode( + subgraphDeployment, + tokens, + _allocationID, + abi.encodePacked(r, s, v) + ); + subgraphService.startService(indexer, data); + vm.stopPrank(); + } + + function createIndexingDispute(address _allocationID, uint256 tokens) private returns (bytes32 disputeID) { + vm.startPrank(fisherman); + graphToken.mint(fisherman, tokens); + graphToken.approve(address(disputeManager), tokens); + bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, tokens); + vm.stopPrank(); + return _disputeID; + } + + function createQueryDispute(uint256 tokens) private returns (bytes32 disputeID) { + Attestation.Receipt memory receipt = Attestation.Receipt({ + requestCID: keccak256(abi.encodePacked("Request CID")), + responseCID: keccak256(abi.encodePacked("Response CID")), + subgraphDeploymentId: keccak256(abi.encodePacked("Subgraph Deployment ID")) + }); + bytes memory attestationData = createAtestationData(receipt, allocationIDPrivateKey); + + vm.startPrank(fisherman); + graphToken.mint(fisherman, tokens); + graphToken.approve(address(disputeManager), tokens); + bytes32 _disputeID = disputeManager.createQueryDispute(attestationData, tokens); + vm.stopPrank(); + return _disputeID; + } + + function createConflictingAttestations( + bytes32 responseCID1, + bytes32 subgraphDeploymentId1, + bytes32 responseCID2, + bytes32 subgraphDeploymentId2 + ) private view returns (bytes memory attestationData1, bytes memory attestationData2) { + bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); + Attestation.Receipt memory receipt1 = Attestation.Receipt({ + requestCID: requestCID, + responseCID: responseCID1, + subgraphDeploymentId: subgraphDeploymentId1 + }); + + Attestation.Receipt memory receipt2 = Attestation.Receipt({ + requestCID: requestCID, + responseCID: responseCID2, + subgraphDeploymentId: subgraphDeploymentId2 + }); + + bytes memory _attestationData1 = createAtestationData(receipt1, allocationIDPrivateKey); + bytes memory _attestationData2 = createAtestationData(receipt2, allocationIDPrivateKey); + return (_attestationData1, _attestationData2); + } + + function createAtestationData(Attestation.Receipt memory receipt, uint256 signer) private view returns (bytes memory attestationData) { + bytes32 digest = disputeManager.encodeReceipt(receipt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); + + return abi.encodePacked(receipt.requestCID, receipt.responseCID, receipt.subgraphDeploymentId, r, s, v); + } + + // Tests + + // Create dispute + + function testCreateIndexingDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); + } + + function testCreateQueryDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + + bytes32 disputeID = createQueryDispute(200 ether); + assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); + } + + function testCreateQueryDisputeConflict() public { + createProvisionAndAllocate(allocationID, 10000 ether); + + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = + createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + vm.prank(fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + assertTrue(disputeManager.isDisputeCreated(disputeID1), "Dispute 1 should be created."); + assertTrue(disputeManager.isDisputeCreated(disputeID2), "Dispute 2 should be created."); + } + + function test_RevertWhen_DisputeAlreadyCreated() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + // Create another dispute with different fisherman + address otherFisherman = address(0x5); + uint256 tokens = 200 ether; + vm.startPrank(otherFisherman); + graphToken.mint(otherFisherman, tokens); + graphToken.approve(address(disputeManager), tokens); + bytes memory expectedError = abi.encodeWithSignature("DisputeManagerDisputeAlreadyCreated(bytes32)", disputeID); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, tokens); + vm.stopPrank(); + } + + function test_RevertIf_DepositUnderMinimum() public { + // minimum deposit is 100 ether + vm.startPrank(fisherman); + graphToken.mint(fisherman, 50 ether); + bytes memory expectedError = abi.encodeWithSignature("DisputeManagerInsufficientDeposit(uint256,uint256)", 50 ether, 100 ether); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, 50 ether); + vm.stopPrank(); + } + + function test_RevertIf_AllocationDoesNotExist() public { + // create dispute without an existing allocation + uint256 tokens = 200 ether; + vm.startPrank(fisherman); + graphToken.mint(fisherman, tokens); + graphToken.approve(address(disputeManager), tokens); + bytes memory expectedError = abi.encodeWithSignature("DisputeManagerIndexerNotFound(address)", allocationID); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, tokens); + vm.stopPrank(); + } + + function test_RevertIf_ConflictingAttestationsResponsesAreTheSame() public { + bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 responseCID = keccak256(abi.encodePacked("Response CID")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = + createConflictingAttestations( + responseCID, + subgraphDeploymentId, + responseCID, + subgraphDeploymentId + ); + + vm.prank(fisherman); + + bytes memory expectedError = abi.encodeWithSignature( + "DisputeManagerNonConflictingAttestations(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32)", + requestCID, + responseCID, + subgraphDeploymentId, + requestCID, + responseCID, + subgraphDeploymentId + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + } + + function test_RevertIf_ConflictingAttestationsHaveDifferentSubgraph() public { + bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId1 = keccak256(abi.encodePacked("Subgraph Deployment ID 1")); + bytes32 subgraphDeploymentId2 = keccak256(abi.encodePacked("Subgraph Deployment ID 2")); + + (bytes memory attestationData1, bytes memory attestationData2) = + createConflictingAttestations( + responseCID1, + subgraphDeploymentId1, + responseCID2, + subgraphDeploymentId2 + ); + + vm.prank(fisherman); + bytes memory expectedError = abi.encodeWithSignature( + "DisputeManagerNonConflictingAttestations(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32)", + requestCID, + responseCID1, + subgraphDeploymentId1, + requestCID, + responseCID2, + subgraphDeploymentId2 + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + } + + // Accept dispute + + function testAcceptIndexingDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + vm.prank(arbitrator); + disputeManager.acceptDispute(disputeID, 5000 ether); + + assertEq(graphToken.balanceOf(fisherman), 700 ether, "Fisherman should receive 50% of slashed tokens."); + assertEq(graphToken.balanceOf(indexer), 5000 ether, "Service provider should have 5000 GRT slashed."); + } + + function testAcceptQueryDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createQueryDispute(200 ether); + + vm.prank(arbitrator); + disputeManager.acceptDispute(disputeID, 5000 ether); + + assertEq(graphToken.balanceOf(fisherman), 700 ether, "Fisherman should receive 50% of slashed tokens."); + assertEq(graphToken.balanceOf(indexer), 5000 ether, "Service provider should have 5000 GRT slashed."); + } + + function testAcceptQueryDisputeConflicting() public { + createProvisionAndAllocate(allocationID, 10000 ether); + + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = + createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + vm.prank(fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + + vm.prank(arbitrator); + disputeManager.acceptDispute(disputeID1, 5000 ether); + + assertEq(graphToken.balanceOf(fisherman), 500 ether, "Fisherman should receive 50% of slashed tokens."); + assertEq(graphToken.balanceOf(indexer), 5000 ether, "Service provider should have 5000 GRT slashed."); + + (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + assertTrue(status1 == IDisputeManager.DisputeStatus.Accepted, "Dispute 1 should be accepted."); + assertTrue(status2 == IDisputeManager.DisputeStatus.Rejected, "Dispute 2 should be rejected."); + } + + function test_RevertIf_CallerIsNotArbitrator_AcceptDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + // attempt to accept dispute as fisherman + vm.prank(fisherman); + vm.expectRevert(bytes4(keccak256("DisputeManagerNotArbitrator()"))); + disputeManager.acceptDispute(disputeID, 5000 ether); + } + + function test_RevertIf_SlashingOverMaxSlashPercentage() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + // max slashing percentage is 50% + vm.prank(arbitrator); + bytes memory expectedError = abi.encodeWithSignature("DisputeManagerInvalidSlashAmount(uint256)", 6000 ether); + vm.expectRevert(expectedError); + disputeManager.acceptDispute(disputeID, 6000 ether); + } + + // Cancel dispute + + function testCancelDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + // skip to end of dispute period + skip(disputePeriod + 1); + + vm.prank(fisherman); + disputeManager.cancelDispute(disputeID); + + assertEq(graphToken.balanceOf(fisherman), 200 ether, "Fisherman should receive their deposit back."); + assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); + } + + function testCancelQueryDisputeConflicting() public { + createProvisionAndAllocate(allocationID, 10000 ether); + + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = + createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + vm.prank(fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + + // skip to end of dispute period + skip(disputePeriod + 1); + + vm.prank(fisherman); + disputeManager.cancelDispute(disputeID1); + + assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); + + (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + assertTrue(status1 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 1 should be cancelled."); + assertTrue(status2 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 2 should be cancelled."); + } + + function test_RevertIf_CallerIsNotFisherman_CancelDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + vm.prank(arbitrator); + vm.expectRevert(bytes4(keccak256("DisputeManagerNotFisherman()"))); + disputeManager.cancelDispute(disputeID); + } + + // Draw dispute + + function testDrawDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + vm.prank(arbitrator); + disputeManager.drawDispute(disputeID); + + assertEq(graphToken.balanceOf(fisherman), 200 ether, "Fisherman should receive their deposit back."); + assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); + } + + function testDrawQueryDisputeConflicting() public { + createProvisionAndAllocate(allocationID, 10000 ether); + + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = + createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + vm.prank(fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + + vm.prank(arbitrator); + disputeManager.drawDispute(disputeID1); + + assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); + + (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + assertTrue(status1 == IDisputeManager.DisputeStatus.Drawn, "Dispute 1 should be drawn."); + assertTrue(status2 == IDisputeManager.DisputeStatus.Drawn, "Dispute 2 should be drawn."); + } + + function test_RevertIf_CallerIsNotArbitrator_DrawDispute() public { + createProvisionAndAllocate(allocationID, 10000 ether); + bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + + // attempt to draw dispute as fisherman + vm.prank(fisherman); + vm.expectRevert(bytes4(keccak256("DisputeManagerNotArbitrator()"))); + disputeManager.drawDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/mocks/MockGRTToken.sol b/packages/subgraph-service/test/mocks/MockGRTToken.sol new file mode 100644 index 000000000..11cf5c0f8 --- /dev/null +++ b/packages/subgraph-service/test/mocks/MockGRTToken.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; + +contract MockGRTToken is ERC20, IGraphToken { + constructor() ERC20("Graph Token", "GRT") {} + + function burn(uint256 amount) external {} + + function burnFrom(address _from, uint256 amount) external { + _burn(_from, amount); + } + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } + + // -- Mint Admin -- + + function addMinter(address _account) external {} + + function removeMinter(address _account) external {} + + function renounceMinter() external {} + + function isMinter(address _account) external view returns (bool) {} + + // -- Permit -- + + function permit( + address _owner, + address _spender, + uint256 _value, + uint256 _deadline, + uint8 _v, + bytes32 _r, + bytes32 _s + ) external {} + + // -- Allowance -- + + function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {} + function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {} +} \ No newline at end of file diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol new file mode 100644 index 000000000..bd67a980c --- /dev/null +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { MockGRTToken } from "./MockGRTToken.sol"; + +contract MockHorizonStaking is IHorizonStaking { + mapping (address verifier => mapping (address serviceProvider => IHorizonStaking.Provision provision)) public _provisions; + MockGRTToken public grtToken; + + constructor(address _grtTokenAddress) { + grtToken = MockGRTToken(_grtTokenAddress); + } + + // whitelist/deny a verifier + function allowVerifier(address verifier, bool allow) external {} + + // deposit stake + function stake(uint256 tokens) external {} + + // create a provision + function provision(uint256 tokens, address verifier, uint32 maxVerifierCut, uint64 thawingPeriod) external { + IHorizonStaking.Provision memory newProvision = IHorizonStaking.Provision({ + serviceProvider: msg.sender, + tokens: tokens, + delegatedTokens: 0, + tokensThawing: 0, + createdAt: uint64(block.timestamp), + verifier: verifier, + maxVerifierCut: maxVerifierCut, + thawingPeriod: thawingPeriod + }); + _provisions[verifier][msg.sender] = newProvision; + } + + function acceptProvision(address serviceProvider) external {} + + // initiate a thawing to remove tokens from a provision + function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId) {} + + // moves thawed stake from a provision back into the provider's available stake + function deprovision(bytes32 thawRequestId) external {} + + // moves thawed stake from one provision into another provision + function reprovision(bytes32 thawRequestId, bytes32 provisionId) external {} + + // moves thawed stake back to the owner's account - stake is removed from the protocol + function withdraw(bytes32 thawRequestId) external {} + + // delegate tokens to a provider + function delegate(address serviceProvider, uint256 tokens) external {} + + // undelegate tokens + function undelegate( + address serviceProvider, + uint256 tokens, + bytes32[] calldata provisions + ) external returns (bytes32 thawRequestId) {} + + // slash a service provider + function slash(address serviceProvider, uint256 tokens, uint256 reward, address rewardsDestination) external { + grtToken.mint(rewardsDestination, reward); + grtToken.burnFrom(serviceProvider, tokens); + } + + // set the Service Provider's preferred provisions to be force thawed + function setForceThawProvisions(bytes32[] calldata provisions) external {} + + // total staked tokens to the provider + // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` + function getStake(address serviceProvider) external view returns (uint256 tokens) {} + + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address serviceProvider) external view returns (uint256 tokens) {} + + // staked tokens the provider can provision before hitting the delegation cap + // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` + function getCapacity(address serviceProvider) external view returns (uint256 tokens) {} + + // provisioned tokens that are not being used + // `Provision.tokens - Provision.tokensThawing` + function getTokensAvailable(address serviceProvider, address verifier) external view returns (uint256 tokens) { + return _provisions[verifier][serviceProvider].tokens; + } + + function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory) {} + + function getProvision(address serviceProvider, address verifier) external view returns (Provision memory) { + return _provisions[verifier][serviceProvider]; + } + + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param _operator The address to check for auth + * @param _serviceProvider The service provider on behalf of whom they're claiming to act + * @param _verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized(address _operator, address _serviceProvider, address _verifier) external view returns (bool) { + return true; + } + + function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256 delegationCut) {} + function addToDelegationPool(address serviceProvider, uint256 tokens) external {} + function stakeToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external {} +} \ No newline at end of file diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol new file mode 100644 index 000000000..6d15d2b3c --- /dev/null +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; + +contract MockRewardsManager is IRewardsManager { + // -- Config -- + + function setIssuancePerBlock(uint256 _issuancePerBlock) external {} + + function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external {} + + // -- Denylist -- + + function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external {} + + function setDenied(bytes32 _subgraphDeploymentID, bool _deny) external {} + + function setDeniedMany(bytes32[] calldata _subgraphDeploymentID, bool[] calldata _deny) external {} + + function isDenied(bytes32 _subgraphDeploymentID) external view returns (bool) {} + + // -- Getters -- + + function getNewRewardsPerSignal() external view returns (uint256) {} + + function getAccRewardsPerSignal() external view returns (uint256) {} + + function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) external view returns (uint256) {} + + function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID) external view returns (uint256, uint256) {} + + function getRewards(address _allocationID) external view returns (uint256) {} + + // -- Updates -- + + function updateAccRewardsPerSignal() external returns (uint256) {} + + function takeRewards(address _allocationID) external returns (uint256) {} + + // -- Hooks -- + + function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external returns (uint256) {} + + function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) external returns (uint256) { + return 0; + } +} \ No newline at end of file diff --git a/packages/subgraph-service/tsconfig.json b/packages/subgraph-service/tsconfig.json new file mode 100644 index 000000000..adee669ce --- /dev/null +++ b/packages/subgraph-service/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": [ + "hardhat.config.ts", + "prettier.config.js", + "scripts/**/*.ts", + "test/**/*.ts", + "eslint.config.js" + ] +} diff --git a/yarn.lock b/yarn.lock index 00e728326..1e14c7d52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,22 +5,15 @@ __metadata: version: 8 cacheKey: 10c0 -"@0no-co/graphql.web@npm:^1.0.1": - version: 1.0.4 - resolution: "@0no-co/graphql.web@npm:1.0.4" +"@0no-co/graphql.web@npm:^1.0.5": + version: 1.0.7 + resolution: "@0no-co/graphql.web@npm:1.0.7" peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 peerDependenciesMeta: graphql: optional: true - checksum: bf63cb5b017063363c9a9e06dc17532abc1c2da402c7ebcbc7b5ab2a0601ec93b02de93af9e50d9daffb3b747eddcf0b1e5418a46d1182c5b8087b7d7a1768ad - languageName: node - linkType: hard - -"@aashutoshrathi/word-wrap@npm:^1.2.3": - version: 1.2.6 - resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" - checksum: 53c2b231a61a46792b39a0d43bc4f4f776bb4542aa57ee04930676802e5501282c2fc8aac14e4cd1f1120ff8b52616b6ff5ab539ad30aa2277d726444b71619f + checksum: 4744a6c327e0a2d564c8f4720ef08dcece6c3b8373f52208ff29f7086f90e18d211c59cc222c229f1e3241abd1fc6e30377dc1dadac491bbb25706f29dea626a languageName: node linkType: hard @@ -32,12 +25,12 @@ __metadata: linkType: hard "@ampproject/remapping@npm:^2.2.0": - version: 2.2.1 - resolution: "@ampproject/remapping@npm:2.2.1" + version: 2.3.0 + resolution: "@ampproject/remapping@npm:2.3.0" dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.0" - "@jridgewell/trace-mapping": "npm:^0.3.9" - checksum: 92ce5915f8901d8c7cd4f4e6e2fe7b9fd335a29955b400caa52e0e5b12ca3796ada7c2f10e78c9c5b0f9c2539dff0ffea7b19850a56e1487aa083531e1e46d43 + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 81d63cca5443e0f0c72ae18b544cc28c7c0ec2cea46e7cb888bb0e0f411a1191d0d6b7af798d54e30777d8d1488b2ec0732aac2be342d3d7d3ffd271c6f489ed languageName: node linkType: hard @@ -129,12 +122,12 @@ __metadata: linkType: hard "@aws-sdk/types@npm:^3.1.0": - version: 3.515.0 - resolution: "@aws-sdk/types@npm:3.515.0" + version: 3.577.0 + resolution: "@aws-sdk/types@npm:3.577.0" dependencies: - "@smithy/types": "npm:^2.9.1" - tslib: "npm:^2.5.0" - checksum: 47afecf060dec7e7db5073dfec7d6815582f66266cfb31111af4a80fc10bc56bf5c7a5dc096780849efa982a9b097e69b1b3bebf23d82521763b04ae17cc7202 + "@smithy/types": "npm:^3.0.0" + tslib: "npm:^2.6.2" + checksum: ae31757b05c2445f52b3f3268d7e9cbae765cae24f088afb8f967c8e3a268b425794a8e99fab3e0428dc6491ccca99b6c57ab5ca69e2d1cc2878ec85ff9643f7 languageName: node linkType: hard @@ -147,55 +140,55 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/code-frame@npm:7.23.5" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.2": + version: 7.24.2 + resolution: "@babel/code-frame@npm:7.24.2" dependencies: - "@babel/highlight": "npm:^7.23.4" - chalk: "npm:^2.4.2" - checksum: a10e843595ddd9f97faa99917414813c06214f4d9205294013e20c70fbdf4f943760da37dec1d998bf3e6fc20fa2918a47c0e987a7e458663feb7698063ad7c6 + "@babel/highlight": "npm:^7.24.2" + picocolors: "npm:^1.0.0" + checksum: d1d4cba89475ab6aab7a88242e1fd73b15ecb9f30c109b69752956434d10a26a52cbd37727c4eca104b6d45227bd1dfce39a6a6f4a14c9b2f07f871e968cf406 languageName: node linkType: hard "@babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/compat-data@npm:7.23.5" - checksum: 081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c + version: 7.24.4 + resolution: "@babel/compat-data@npm:7.24.4" + checksum: 9cd8a9cd28a5ca6db5d0e27417d609f95a8762b655e8c9c97fd2de08997043ae99f0139007083c5e607601c6122e8432c85fe391731b19bf26ad458fa0c60dd3 languageName: node linkType: hard "@babel/core@npm:^7.14.0": - version: 7.23.9 - resolution: "@babel/core@npm:7.23.9" + version: 7.24.5 + resolution: "@babel/core@npm:7.24.5" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.23.5" - "@babel/generator": "npm:^7.23.6" + "@babel/code-frame": "npm:^7.24.2" + "@babel/generator": "npm:^7.24.5" "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.9" - "@babel/parser": "npm:^7.23.9" - "@babel/template": "npm:^7.23.9" - "@babel/traverse": "npm:^7.23.9" - "@babel/types": "npm:^7.23.9" + "@babel/helper-module-transforms": "npm:^7.24.5" + "@babel/helpers": "npm:^7.24.5" + "@babel/parser": "npm:^7.24.5" + "@babel/template": "npm:^7.24.0" + "@babel/traverse": "npm:^7.24.5" + "@babel/types": "npm:^7.24.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 03883300bf1252ab4c9ba5b52f161232dd52873dbe5cde9289bb2bb26e935c42682493acbac9194a59a3b6cbd17f4c4c84030db8d6d482588afe64531532ff9b + checksum: e26ba810a77bc8e21579a12fc36c79a0a60554404dc9447f2d64eb1f26d181c48d3b97d39d9f158e9911ec7162a8280acfaf2b4b210e975f0dd4bd4dbb1ee159 languageName: node linkType: hard -"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/generator@npm:7.23.6" +"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/generator@npm:7.24.5" dependencies: - "@babel/types": "npm:^7.23.6" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" + "@babel/types": "npm:^7.24.5" + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 53540e905cd10db05d9aee0a5304e36927f455ce66f95d1253bb8a179f286b88fa7062ea0db354c566fe27f8bb96567566084ffd259f8feaae1de5eccc8afbda + checksum: 0d64f880150e7dfb92ceff2b4ac865f36aa1e295120920246492ffd0146562dabf79ba8699af1c8833f8a7954818d4d146b7b02f808df4d6024fb99f98b2f78d languageName: node linkType: hard @@ -208,7 +201,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.20.7, @babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.23.6": +"@babel/helper-compilation-targets@npm:^7.20.7, @babel/helper-compilation-targets@npm:^7.23.6": version: 7.23.6 resolution: "@babel/helper-compilation-targets@npm:7.23.6" dependencies: @@ -222,21 +215,21 @@ __metadata: linkType: hard "@babel/helper-create-class-features-plugin@npm:^7.18.6": - version: 7.23.10 - resolution: "@babel/helper-create-class-features-plugin@npm:7.23.10" + version: 7.24.5 + resolution: "@babel/helper-create-class-features-plugin@npm:7.24.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-member-expression-to-functions": "npm:^7.23.0" + "@babel/helper-member-expression-to-functions": "npm:^7.24.5" "@babel/helper-optimise-call-expression": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.20" + "@babel/helper-replace-supers": "npm:^7.24.1" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/helper-split-export-declaration": "npm:^7.24.5" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: f30437aa16f3585cc3382ea630f24457ef622c22f5e4eccffbc03f6a81efbef0b6714fb5a78baa64c838884ba7e1427e3280d7b27481b9f587bc8fbbed05dd36 + checksum: afc72e8075a249663f8024ef1760de4c0b9252bdde16419ac955fa7e15b8d4096ca1e01f796df4fa8cfdb056708886f60b631ad492242a8e47307974fc305920 languageName: node linkType: hard @@ -266,36 +259,36 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.22.15, @babel/helper-member-expression-to-functions@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" +"@babel/helper-member-expression-to-functions@npm:^7.23.0, @babel/helper-member-expression-to-functions@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-member-expression-to-functions@npm:7.24.5" dependencies: - "@babel/types": "npm:^7.23.0" - checksum: b810daddf093ffd0802f1429052349ed9ea08ef7d0c56da34ffbcdecbdafac86f95bdea2fe30e0e0e629febc7dd41b56cb5eacc10d1a44336d37b755dac31fa4 + "@babel/types": "npm:^7.24.5" + checksum: a3c0276a1ede8648a0e6fd86ad846cd57421d05eddfa29446b8b5a013db650462022b9ec1e65ea32c747d0542d729c80866830697f94fb12d603e87c51f080a5 languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-module-imports@npm:7.22.15" +"@babel/helper-module-imports@npm:^7.22.15, @babel/helper-module-imports@npm:^7.24.3": + version: 7.24.3 + resolution: "@babel/helper-module-imports@npm:7.24.3" dependencies: - "@babel/types": "npm:^7.22.15" - checksum: 4e0d7fc36d02c1b8c8b3006dfbfeedf7a367d3334a04934255de5128115ea0bafdeb3e5736a2559917f0653e4e437400d54542da0468e08d3cbc86d3bbfa8f30 + "@babel/types": "npm:^7.24.0" + checksum: 052c188adcd100f5e8b6ff0c9643ddaabc58b6700d3bbbc26804141ad68375a9f97d9d173658d373d31853019e65f62610239e3295cdd58e573bdcb2fded188d languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/helper-module-transforms@npm:7.23.3" +"@babel/helper-module-transforms@npm:^7.23.3, @babel/helper-module-transforms@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-module-transforms@npm:7.24.5" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-module-imports": "npm:^7.22.15" - "@babel/helper-simple-access": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.24.3" + "@babel/helper-simple-access": "npm:^7.24.5" + "@babel/helper-split-export-declaration": "npm:^7.24.5" + "@babel/helper-validator-identifier": "npm:^7.24.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 211e1399d0c4993671e8e5c2b25383f08bee40004ace5404ed4065f0e9258cc85d99c1b82fd456c030ce5cfd4d8f310355b54ef35de9924eabfc3dff1331d946 + checksum: 6e77d72f62b7e87abaea800ea0bccd4d54cde26485750969f5f493c032eb63251eb50c3522cace557781565d51c1d0c4bcc866407d24becfb109c18fb92c978d languageName: node linkType: hard @@ -308,32 +301,32 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.22.5 - resolution: "@babel/helper-plugin-utils@npm:7.22.5" - checksum: d2c4bfe2fa91058bcdee4f4e57a3f4933aed7af843acfd169cd6179fab8d13c1d636474ecabb2af107dc77462c7e893199aa26632bac1c6d7e025a17cbb9d20d +"@babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.24.5, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.24.5 + resolution: "@babel/helper-plugin-utils@npm:7.24.5" + checksum: 4ae40094e6a2f183281213344f4df60c66b16b19a2bc38d2bb11810a6dc0a0e7ec638957d0e433ff8b615775b8f3cd1b7edbf59440d1b50e73c389fc22913377 languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-replace-supers@npm:7.22.20" +"@babel/helper-replace-supers@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/helper-replace-supers@npm:7.24.1" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-member-expression-to-functions": "npm:^7.22.15" + "@babel/helper-member-expression-to-functions": "npm:^7.23.0" "@babel/helper-optimise-call-expression": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 6b0858811ad46873817c90c805015d63300e003c5a85c147a17d9845fa2558a02047c3cc1f07767af59014b2dd0fa75b503e5bc36e917f360e9b67bb6f1e79f4 + checksum: d39a3df7892b7c3c0e307fb229646168a9bd35e26a72080c2530729322600e8cff5f738f44a14860a2358faffa741b6a6a0d6749f113387b03ddbfa0ec10e1a0 languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-simple-access@npm:7.22.5" +"@babel/helper-simple-access@npm:^7.22.5, @babel/helper-simple-access@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-simple-access@npm:7.24.5" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: f0cf81a30ba3d09a625fd50e5a9069e575c5b6719234e04ee74247057f8104beca89ed03e9217b6e9b0493434cedc18c5ecca4cea6244990836f1f893e140369 + "@babel/types": "npm:^7.24.5" + checksum: d96a0ab790a400f6c2dcbd9457b9ca74b9ba6d0f67ff9cd5bcc73792c8fbbd0847322a0dddbd8987dd98610ee1637c680938c7d83d3ffce7d06d7519d823d996 languageName: node linkType: hard @@ -346,26 +339,26 @@ __metadata: languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/helper-split-export-declaration@npm:7.22.6" +"@babel/helper-split-export-declaration@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-split-export-declaration@npm:7.24.5" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: d83e4b623eaa9622c267d3c83583b72f3aac567dc393dda18e559d79187961cb29ae9c57b2664137fc3d19508370b12ec6a81d28af73a50e0846819cb21c6e44 + "@babel/types": "npm:^7.24.5" + checksum: d7a812d67d031a348f3fb0e6263ce2dbe6038f81536ba7fb16db385383bcd6542b71833194303bf6d3d0e4f7b6b584c9c8fae8772122e2ce68fc9bdf07f4135d languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/helper-string-parser@npm:7.23.4" - checksum: f348d5637ad70b6b54b026d6544bd9040f78d24e7ec245a0fc42293968181f6ae9879c22d89744730d246ce8ec53588f716f102addd4df8bbc79b73ea10004ac +"@babel/helper-string-parser@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/helper-string-parser@npm:7.24.1" + checksum: 2f9bfcf8d2f9f083785df0501dbab92770111ece2f90d120352fda6dd2a7d47db11b807d111e6f32aa1ba6d763fe2dc6603d153068d672a5d0ad33ca802632b2 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: dcad63db345fb110e032de46c3688384b0008a42a4845180ce7cd62b1a9c0507a1bed727c4d1060ed1a03ae57b4d918570259f81724aaac1a5b776056f37504e +"@babel/helper-validator-identifier@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-validator-identifier@npm:7.24.5" + checksum: 05f957229d89ce95a137d04e27f7d0680d84ae48b6ad830e399db0779341f7d30290f863a93351b4b3bde2166737f73a286ea42856bb07c8ddaa95600d38645c languageName: node linkType: hard @@ -376,34 +369,35 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.9": - version: 7.23.9 - resolution: "@babel/helpers@npm:7.23.9" +"@babel/helpers@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helpers@npm:7.24.5" dependencies: - "@babel/template": "npm:^7.23.9" - "@babel/traverse": "npm:^7.23.9" - "@babel/types": "npm:^7.23.9" - checksum: f69fd0aca96a6fb8bd6dd044cd8a5c0f1851072d4ce23355345b9493c4032e76d1217f86b70df795e127553cf7f3fcd1587ede9d1b03b95e8b62681ca2165b87 + "@babel/template": "npm:^7.24.0" + "@babel/traverse": "npm:^7.24.5" + "@babel/types": "npm:^7.24.5" + checksum: 0630b0223c3a9a34027ddc05b3bac54d68d5957f84e92d2d4814b00448a76e12f9188f9c85cfce2011696d82a8ffcbd8189da097c0af0181d32eb27eca34185e languageName: node linkType: hard -"@babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" +"@babel/highlight@npm:^7.24.2": + version: 7.24.5 + resolution: "@babel/highlight@npm:7.24.5" dependencies: - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-validator-identifier": "npm:^7.24.5" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" - checksum: fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 + picocolors: "npm:^1.0.0" + checksum: e98047d3ad24608bfa596d000c861a2cc875af897427f2833b91a4e0d4cead07301a7ec15fa26093dcd61e036e2eed2db338ae54f93016fe0dc785fadc4159db languageName: node linkType: hard -"@babel/parser@npm:^7.14.0, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.23.9": - version: 7.23.9 - resolution: "@babel/parser@npm:7.23.9" +"@babel/parser@npm:^7.14.0, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/parser@npm:7.24.5" bin: parser: ./bin/babel-parser.js - checksum: 7df97386431366d4810538db4b9ec538f4377096f720c0591c7587a16f6810e62747e9fbbfa1ff99257fd4330035e4fb1b5b77c7bd3b97ce0d2e3780a6618975 + checksum: 8333a6ad5328bad34fa0e12bcee147c3345ea9a438c0909e7c68c6cfbea43c464834ffd7eabd1cbc1c62df0a558e22ffade9f5b29440833ba7b33d96a71f88c0 languageName: node linkType: hard @@ -445,36 +439,36 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-syntax-flow@npm:7.23.3" +"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-syntax-flow@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8a5e1e8b6a3728a2c8fe6d70c09a43642e737d9c0485e1b041cd3a6021ef05376ec3c9137be3b118c622ba09b5770d26fdc525473f8d06d4ab9e46de2783dd0a + checksum: 618de04360a96111408abdaafaba2efbaef0d90faad029d50e0281eaad5d7c7bd2ce4420bbac0ee27ad84c2b7bbc3e48f782064f81ed5bc40c398637991004c7 languageName: node linkType: hard "@babel/plugin-syntax-import-assertions@npm:^7.20.0": - version: 7.23.3 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7db8b59f75667bada2293353bb66b9d5651a673b22c72f47da9f5c46e719142481601b745f9822212fd7522f92e26e8576af37116f85dae1b5e5967f80d0faab + checksum: 72f0340d73e037f0702c61670054e0af66ece7282c5c2f4ba8de059390fee502de282defdf15959cd9f71aa18dc5c5e4e7a0fde317799a0600c6c4e0a656d82b languageName: node linkType: hard "@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-syntax-jsx@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 563bb7599b868773f1c7c1d441ecc9bc53aeb7832775da36752c926fc402a1fa5421505b39e724f71eb217c13e4b93117e081cac39723b0e11dac4c897f33c3e + checksum: 6cec76fbfe6ca81c9345c2904d8d9a8a0df222f9269f0962ed6eb2eb8f3f10c2f15e993d1ef09dbaf97726bf1792b5851cf5bd9a769f966a19448df6be95d19a languageName: node linkType: hard @@ -490,193 +484,193 @@ __metadata: linkType: hard "@babel/plugin-transform-arrow-functions@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b128315c058f5728d29b0b78723659b11de88247ea4d0388f0b935cddf60a80c40b9067acf45cbbe055bd796928faef152a09d9e4a0695465aca4394d9f109ca + checksum: f44bfacf087dc21b422bab99f4e9344ee7b695b05c947dacae66de05c723ab9d91800be7edc1fa016185e8c819f3aca2b4a5f66d8a4d1e47d9bad80b8fa55b8e languageName: node linkType: hard "@babel/plugin-transform-block-scoped-functions@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 82c12a11277528184a979163de7189ceb00129f60dd930b0d5313454310bf71205f302fb2bf0430247161c8a22aaa9fb9eec1459f9f7468206422c191978fd59 + checksum: 6fbaa85f5204f34845dfc0bebf62fdd3ac5a286241c85651e59d426001e7a1785ac501f154e093e0b8ee49e1f51e3f8b06575a5ae8d4a9406d43e4816bf18c37 languageName: node linkType: hard "@babel/plugin-transform-block-scoping@npm:^7.0.0": - version: 7.23.4 - resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" + version: 7.24.5 + resolution: "@babel/plugin-transform-block-scoping@npm:7.24.5" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 83006804dddf980ab1bcd6d67bc381e24b58c776507c34f990468f820d0da71dba3697355ca4856532fa2eeb2a1e3e73c780f03760b5507a511cbedb0308e276 + checksum: 85997fc8179b7d26e8af30865aeb91789f3bc1f0cd5643ed25f25891ff9c071460ec1220599b19070b424a3b902422f682e9b02e515872540173eae2e25f760c languageName: node linkType: hard "@babel/plugin-transform-classes@npm:^7.0.0": - version: 7.23.8 - resolution: "@babel/plugin-transform-classes@npm:7.23.8" + version: 7.24.5 + resolution: "@babel/plugin-transform-classes@npm:7.24.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.20" - "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-replace-supers": "npm:^7.24.1" + "@babel/helper-split-export-declaration": "npm:^7.24.5" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 227ac5166501e04d9e7fbd5eda6869b084ffa4af6830ac12544ac6ea14953ca00eb1762b0df9349c0f6c8d2a799385910f558066cd0fb85b9ca437b1131a6043 + checksum: 4affcbb7cb01fa4764c7a4b534c30fd24a4b68e680a2d6e242dd7ca8726490f0f1426c44797deff84a38a162e0629718900c68d28daffe2b12adf5b4194156a7 languageName: node linkType: hard "@babel/plugin-transform-computed-properties@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-computed-properties@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-computed-properties@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/template": "npm:^7.22.15" + "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/template": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3ca8a006f8e652b58c21ecb84df1d01a73f0a96b1d216fd09a890b235dd90cb966b152b603b88f7e850ae238644b1636ce5c30b7c029c0934b43383932372e4a + checksum: 8292c508b656b7722e2c2ca0f6f31339852e3ed2b9b80f6e068a4010e961b431ca109ecd467fc906283f4b1574c1e7b1cb68d35a4dea12079d386c15ff7e0eac languageName: node linkType: hard "@babel/plugin-transform-destructuring@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-destructuring@npm:7.23.3" + version: 7.24.5 + resolution: "@babel/plugin-transform-destructuring@npm:7.24.5" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 717e9a62c1b0c93c507f87b4eaf839ec08d3c3147f14d74ae240d8749488d9762a8b3950132be620a069bde70f4b3e4ee9867b226c973fcc40f3cdec975cde71 + checksum: 6a37953a95f04b335bf3e2118fb93f50dd9593c658d1b2f8918a380a2ee30f1b420139eccf7ec3873c86a8208527895fcf6b7e21c0e734a6ad6e5d5042eace4d languageName: node linkType: hard "@babel/plugin-transform-flow-strip-types@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/plugin-syntax-flow": "npm:^7.23.3" + "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/plugin-syntax-flow": "npm:^7.24.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9ab627f9668fc1f95564b26bffd6706f86205960d9ccc168236752fbef65dbe10aa0ce74faae12f48bb3b72ec7f38ef2a78b4874c222c1e85754e981639f3b33 + checksum: e6aa9cbad0441867598d390d4df65bc8c6b797574673e4eedbdae0cc528e81e00f4b2cd38f7d138b0f04bcdd2540384a9812d5d76af5abfa06aee1c7fc20ca58 languageName: node linkType: hard "@babel/plugin-transform-for-of@npm:^7.0.0": - version: 7.23.6 - resolution: "@babel/plugin-transform-for-of@npm:7.23.6" + version: 7.24.1 + resolution: "@babel/plugin-transform-for-of@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 46681b6ab10f3ca2d961f50d4096b62ab5d551e1adad84e64be1ee23e72eb2f26a1e30e617e853c74f1349fffe4af68d33921a128543b6f24b6d46c09a3e2aec + checksum: e4bc92b1f334246e62d4bde079938df940794db564742034f6597f2e38bd426e11ae8c5670448e15dd6e45c462f2a9ab3fa87259bddf7c08553ffd9457fc2b2c languageName: node linkType: hard "@babel/plugin-transform-function-name@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-function-name@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-function-name@npm:7.24.1" dependencies: - "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 89cb9747802118048115cf92a8f310752f02030549b26f008904990cbdc86c3d4a68e07ca3b5c46de8a46ed4df2cb576ac222c74c56de67253d2a3ddc2956083 + checksum: 65c1735ec3b5e43db9b5aebf3c16171c04b3050c92396b9e22dda0d2aaf51f43fdcf147f70a40678fd9a4ee2272a5acec4826e9c21bcf968762f4c184897ad75 languageName: node linkType: hard "@babel/plugin-transform-literals@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-literals@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-literals@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8292106b106201464c2bfdd5c014fe6a9ca1c0256eb0a8031deb20081e21906fe68b156186f77d993c23eeab6d8d6f5f66e8895eec7ed97ce6de5dbcafbcd7f4 + checksum: a27cc7d565ee57b5a2bf136fa889c5c2f5988545ae7b3b2c83a7afe5dd37dfac80dca88b1c633c65851ce6af7d2095c04c01228657ce0198f918e64b5ccd01fa languageName: node linkType: hard "@babel/plugin-transform-member-expression-literals@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 687f24f3ec60b627fef6e87b9e2770df77f76727b9d5f54fa4c84a495bb24eb4a20f1a6240fa22d339d45aac5eaeb1b39882e941bfd00cf498f9c53478d1ec88 + checksum: 2af731d02aa4c757ef80c46df42264128cbe45bfd15e1812d1a595265b690a44ad036041c406a73411733540e1c4256d8174705ae6b8cfaf757fc175613993fd languageName: node linkType: hard "@babel/plugin-transform-modules-commonjs@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.1" dependencies: "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" "@babel/helper-simple-access": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 5c8840c5c9ecba39367ae17c973ed13dbc43234147b77ae780eec65010e2a9993c5d717721b23e8179f7cf49decdd325c509b241d69cfbf92aa647a1d8d5a37d + checksum: efb3ea2047604a7eb44a9289311ebb29842fe6510ff8b66a77a60440448c65e1312a60dc48191ed98246bdbd163b5b6f3348a0669bcc0e3809e69c7c776b20fa languageName: node linkType: hard "@babel/plugin-transform-object-super@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-object-super@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-object-super@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.20" + "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-replace-supers": "npm:^7.24.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a6856fd8c0afbe5b3318c344d4d201d009f4051e2f6ff6237ff2660593e93c5997a58772b13d639077c3e29ced3440247b29c496cd77b13af1e7559a70009775 + checksum: d30e6b9e59a707efd7ed524fc0a8deeea046011a6990250f2e9280516683138e2d13d9c52daf41d78407bdab0378aef7478326f2a15305b773d851cb6e106157 languageName: node linkType: hard "@babel/plugin-transform-parameters@npm:^7.0.0, @babel/plugin-transform-parameters@npm:^7.20.7": - version: 7.23.3 - resolution: "@babel/plugin-transform-parameters@npm:7.23.3" + version: 7.24.5 + resolution: "@babel/plugin-transform-parameters@npm:7.24.5" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a8d4cbe0f6ba68d158f5b4215c63004fc37a1fdc539036eb388a9792017c8496ea970a1932ccb929308f61e53dc56676ed01d8df6f42bc0a85c7fd5ba82482b7 + checksum: e08b8c46a24b1b21dde7783cb0aeb56ffe9ef6d6f1795649ce76273657158d3bfa5370c6594200ed7d371983b599c8e194b76108dffed9ab5746fe630ef2e8f5 languageName: node linkType: hard "@babel/plugin-transform-property-literals@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-property-literals@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-property-literals@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b2549f23f90cf276c2e3058c2225c3711c2ad1c417e336d3391199445a9776dd791b83be47b2b9a7ae374b40652d74b822387e31fa5267a37bf49c122e1a9747 + checksum: 3bf3e01f7bb8215a8b6d0081b6f86fea23e3a4543b619e059a264ede028bc58cdfb0acb2c43271271915a74917effa547bc280ac636a9901fa9f2fb45623f87e languageName: node linkType: hard "@babel/plugin-transform-react-display-name@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-react-display-name@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-react-display-name@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3aed142af7bd1aed1df2bdad91ed33ba1cdd5c3c67ce6eafba821ff72f129162a197ffb55f1eb1775af276abd5545934489a8257fef6c6665ddf253a4f39a939 + checksum: adf1a3cb0df8134533a558a9072a67e34127fd489dfe431c3348a86dd41f3e74861d5d5134bbb68f61a9cdb3f7e79b2acea1346be94ce4d3328a64e5a9e09be1 languageName: node linkType: hard @@ -696,85 +690,85 @@ __metadata: linkType: hard "@babel/plugin-transform-shorthand-properties@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c423c66fec0b6503f50561741754c84366ef9e9818442c8881fbaa90cc363fd137084b9431cdc00ed2f1fd8c8a1a5982c4a7e1f2af3769db4caf2ac7ea55d4f0 + checksum: 8273347621183aada3cf1f3019d8d5f29467ba13a75b72cb405bc7f23b7e05fd85f4edb1e4d9f0103153dddb61826a42dc24d466480d707f8932c1923a4c25fa languageName: node linkType: hard "@babel/plugin-transform-spread@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-spread@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-spread@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a348e4ae47e4ceeceb760506ec7bf835ccc18a2cf70ec74ebfbe41bc172fa2412b05b7d1b86836f8aee375e41a04ff20486074778d0e2d19d668b33dc52e9dbb + checksum: 50a0302e344546d57e5c9f4dea575f88e084352eeac4e9a3e238c41739eef2df1daf4a7ebbb3ccb7acd3447f6a5ce9938405f98bf5f5583deceb8257f5a673c9 languageName: node linkType: hard "@babel/plugin-transform-template-literals@npm:^7.0.0": - version: 7.23.3 - resolution: "@babel/plugin-transform-template-literals@npm:7.23.3" + version: 7.24.1 + resolution: "@babel/plugin-transform-template-literals@npm:7.24.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9b5f43788b9ffcb8f2b445a16b1aa40fcf23cb0446a4649445f098ec6b4cb751f243a535da623d59fefe48f4c40552f5621187a61811779076bab26863e3373d + checksum: f73bcda5488eb81c6e7a876498d9e6b72be32fca5a4d9db9053491a2d1300cd27b889b463fd2558f3cd5826a85ed00f61d81b234aa55cb5a0abf1b6fa1bd5026 languageName: node linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.5.5": - version: 7.23.9 - resolution: "@babel/runtime@npm:7.23.9" + version: 7.24.5 + resolution: "@babel/runtime@npm:7.24.5" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: e71205fdd7082b2656512cc98e647d9ea7e222e4fe5c36e9e5adc026446fcc3ba7b3cdff8b0b694a0b78bb85db83e7b1e3d4c56ef90726682b74f13249cf952d + checksum: 05730e43e8ba6550eae9fd4fb5e7d9d3cb91140379425abcb2a1ff9cebad518a280d82c4c4b0f57ada26a863106ac54a748d90c775790c0e2cd0ddd85ccdf346 languageName: node linkType: hard -"@babel/template@npm:^7.22.15, @babel/template@npm:^7.23.9": - version: 7.23.9 - resolution: "@babel/template@npm:7.23.9" +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.24.0": + version: 7.24.0 + resolution: "@babel/template@npm:7.24.0" dependencies: "@babel/code-frame": "npm:^7.23.5" - "@babel/parser": "npm:^7.23.9" - "@babel/types": "npm:^7.23.9" - checksum: 0e8b60119433787742bc08ae762bbd8d6755611c4cabbcb7627b292ec901a55af65d93d1c88572326069efb64136ef151ec91ffb74b2df7689bbab237030833a + "@babel/parser": "npm:^7.24.0" + "@babel/types": "npm:^7.24.0" + checksum: 9d3dd8d22fe1c36bc3bdef6118af1f4b030aaf6d7d2619f5da203efa818a2185d717523486c111de8d99a8649ddf4bbf6b2a7a64962d8411cf6a8fa89f010e54 languageName: node linkType: hard -"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.23.9": - version: 7.23.9 - resolution: "@babel/traverse@npm:7.23.9" +"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/traverse@npm:7.24.5" dependencies: - "@babel/code-frame": "npm:^7.23.5" - "@babel/generator": "npm:^7.23.6" + "@babel/code-frame": "npm:^7.24.2" + "@babel/generator": "npm:^7.24.5" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.9" - "@babel/types": "npm:^7.23.9" + "@babel/helper-split-export-declaration": "npm:^7.24.5" + "@babel/parser": "npm:^7.24.5" + "@babel/types": "npm:^7.24.5" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: d1615d1d02f04d47111a7ea4446a1a6275668ca39082f31d51f08380de9502e19862be434eaa34b022ce9a17dbb8f9e2b73a746c654d9575f3a680a7ffdf5630 + checksum: 3f22534bc2b2ed9208e55ef48af3b32939032b23cb9dc4037447cb108640df70bbb0b9fea86e9c58648949fdc2cb14e89aa79ffa3c62a5dd43459a52fe8c01d1 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.8.3": - version: 7.23.9 - resolution: "@babel/types@npm:7.23.9" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.24.0, @babel/types@npm:^7.24.5, @babel/types@npm:^7.8.3": + version: 7.24.5 + resolution: "@babel/types@npm:7.24.5" dependencies: - "@babel/helper-string-parser": "npm:^7.23.4" - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-string-parser": "npm:^7.24.1" + "@babel/helper-validator-identifier": "npm:^7.24.5" to-fast-properties: "npm:^2.0.0" - checksum: edc7bb180ce7e4d2aea10c6972fb10474341ac39ba8fdc4a27ffb328368dfdfbf40fca18e441bbe7c483774500d5c05e222cec276c242e952853dcaf4eb884f7 + checksum: e1284eb046c5e0451b80220d1200e2327e0a8544a2fe45bb62c952e5fdef7099c603d2336b17b6eac3cc046b7a69bfbce67fe56e1c0ea48cd37c65cb88638f2a languageName: node linkType: hard @@ -824,9 +818,9 @@ __metadata: languageName: node linkType: hard -"@changesets/apply-release-plan@npm:^7.0.0": - version: 7.0.0 - resolution: "@changesets/apply-release-plan@npm:7.0.0" +"@changesets/apply-release-plan@npm:^7.0.1": + version: 7.0.1 + resolution: "@changesets/apply-release-plan@npm:7.0.1" dependencies: "@babel/runtime": "npm:^7.20.1" "@changesets/config": "npm:^3.0.0" @@ -841,7 +835,7 @@ __metadata: prettier: "npm:^2.7.1" resolve-from: "npm:^5.0.0" semver: "npm:^7.5.3" - checksum: 5f4c2d6b500d0ade51b31bc03b2475dd0bcaf3a31995f2ad953a6c3b05d3fb588568470bad3093d052f351ecdc6f8e2124d38941210361692b81bf62afbba7d7 + checksum: ca41f84a22a1fd25af4b195956afd393000139581a84528b6d21871e4ce417abf884ad2ef8a8ed7abb49031fed7cbb69226a158df36050aa70ed295636a42369 languageName: node linkType: hard @@ -869,11 +863,11 @@ __metadata: linkType: hard "@changesets/cli@npm:^2.27.1": - version: 2.27.1 - resolution: "@changesets/cli@npm:2.27.1" + version: 2.27.2 + resolution: "@changesets/cli@npm:2.27.2" dependencies: "@babel/runtime": "npm:^7.20.1" - "@changesets/apply-release-plan": "npm:^7.0.0" + "@changesets/apply-release-plan": "npm:^7.0.1" "@changesets/assemble-release-plan": "npm:^6.0.0" "@changesets/changelog-git": "npm:^0.2.0" "@changesets/config": "npm:^3.0.0" @@ -885,7 +879,7 @@ __metadata: "@changesets/pre": "npm:^2.0.0" "@changesets/read": "npm:^0.6.0" "@changesets/types": "npm:^6.0.0" - "@changesets/write": "npm:^0.3.0" + "@changesets/write": "npm:^0.3.1" "@manypkg/get-packages": "npm:^1.1.3" "@types/semver": "npm:^7.5.0" ansi-colors: "npm:^4.1.3" @@ -906,7 +900,7 @@ __metadata: tty-table: "npm:^4.1.5" bin: changeset: bin.js - checksum: c7adc35f22983be9b0f6a8e4c3bc7013208ddf341b637530b88267e78469f0b7af9e36b138bea9f2fe29bb7b44294cd08aa0301a5cba0c6a928824f11d024e04 + checksum: c2fd356b235bb27de0267389af38bca356d1c61892d0d3e114cec2e628aa6e7aadfe1828d9024b9c7d8005c3b968760ab4d781d4ce3a04309d5263d710341bec languageName: node linkType: hard @@ -1046,16 +1040,16 @@ __metadata: languageName: node linkType: hard -"@changesets/write@npm:^0.3.0": - version: 0.3.0 - resolution: "@changesets/write@npm:0.3.0" +"@changesets/write@npm:^0.3.1": + version: 0.3.1 + resolution: "@changesets/write@npm:0.3.1" dependencies: "@babel/runtime": "npm:^7.20.1" "@changesets/types": "npm:^6.0.0" fs-extra: "npm:^7.0.1" human-id: "npm:^1.0.2" prettier: "npm:^2.7.1" - checksum: 537f419d854946cce5694696b6a48ffee0ea1f7b5c97c5246836931886db18153c42a7dea1e74b0e8bf571fcded527e2f443ab362fdb1e4129bd95a61b2d0fe5 + checksum: 6c6ef4c12f93ae10706eea96fae73ab05fddeaa1870102681106a29e4e92c37be9643f214c56187141ab5cf3a4cccb4e8a59212d0fa6c7c26083c5d613878c9a languageName: node linkType: hard @@ -1122,12 +1116,12 @@ __metadata: linkType: hard "@commitlint/config-conventional@npm:^18.4.3": - version: 18.6.2 - resolution: "@commitlint/config-conventional@npm:18.6.2" + version: 18.6.3 + resolution: "@commitlint/config-conventional@npm:18.6.3" dependencies: "@commitlint/types": "npm:^18.6.1" conventional-changelog-conventionalcommits: "npm:^7.0.2" - checksum: ff4ccff3c2992c209703eb7d08f8e1c6d8471d4f0778f384dc0fef490cc023227f1b662f7136a301804d650518e00c7f859aa3eb1a156448f837b2a50206430d + checksum: 047f84598f80f7f793bdb0ffc9cf9059c199da6c5bc12ab87084fa933faee08c9290e3331f6f0d7e07c4f0ffb0b5c678e5036025aeabb8e74af296b9146c6354 languageName: node linkType: hard @@ -1476,12 +1470,10 @@ __metadata: linkType: hard "@defi-wonderland/smock@npm:^2.0.7": - version: 2.3.5 - resolution: "@defi-wonderland/smock@npm:2.3.5" + version: 2.4.0 + resolution: "@defi-wonderland/smock@npm:2.4.0" dependencies: - "@nomicfoundation/ethereumjs-evm": "npm:^1.0.0-rc.3" - "@nomicfoundation/ethereumjs-util": "npm:^8.0.0-rc.3" - "@nomicfoundation/ethereumjs-vm": "npm:^6.0.0-rc.3" + "@nomicfoundation/ethereumjs-util": "npm:^9.0.4" diff: "npm:^5.0.0" lodash.isequal: "npm:^4.5.0" lodash.isequalwith: "npm:^4.4.0" @@ -1493,8 +1485,8 @@ __metadata: "@ethersproject/abstract-signer": ^5 "@nomiclabs/hardhat-ethers": ^2 ethers: ^5 - hardhat: ^2 - checksum: c831563fe6607841d69f5936011398a492f760f52f9cb17626b2949ff3ef7668729acc4a3a944f739417b2d1b99bc6c83580f236189f27431224021c66ac1821 + hardhat: ^2.21.0 + checksum: 166dfb4b9e00c29466f0cf27dc2009e8139f9e6a31e42b74d55f5e6ac690d5f7137ae5acf1b8ff846ae46915608f6de921f2bef47a485088e57d951cac72b054 languageName: node linkType: hard @@ -1575,7 +1567,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" checksum: c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 @@ -1599,13 +1591,6 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.56.0": - version: 8.56.0 - resolution: "@eslint/js@npm:8.56.0" - checksum: 60b3a1cf240e2479cec9742424224465dc50e46d781da1b7f5ef240501b2d1202c225bd456207faac4b34a64f4765833345bc4ddffd00395e1db40fa8c426f5a - languageName: node - linkType: hard - "@eslint/js@npm:8.57.0": version: 8.57.0 resolution: "@eslint/js@npm:8.57.0" @@ -2617,9 +2602,9 @@ __metadata: linkType: hard "@fastify/busboy@npm:^2.0.0": - version: 2.1.0 - resolution: "@fastify/busboy@npm:2.1.0" - checksum: 7bb641080aac7cf01d88749ad331af10ba9ec3713ec07cabbe833908c75df21bd56249bb6173bdec07f5a41896b21e3689316f86684c06635da45f91ff4565a2 + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 6f8027a8cba7f8f7b736718b013f5a38c0476eea67034c94a0d3c375e2b114366ad4419e6a6fa7ffc2ef9c6d3e0435d76dd584a7a1cbac23962fda7650b579e3 languageName: node linkType: hard @@ -3009,6 +2994,45 @@ __metadata: languageName: unknown linkType: soft +"@graphprotocol/subgraph-service@workspace:packages/subgraph-service": + version: 0.0.0-use.local + resolution: "@graphprotocol/subgraph-service@workspace:packages/subgraph-service" + dependencies: + "@graphprotocol/contracts": "workspace:^7.0.0" + "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.0" + "@nomicfoundation/hardhat-ethers": "npm:^3.0.0" + "@nomicfoundation/hardhat-foundry": "npm:^1.1.1" + "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0" + "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" + "@nomicfoundation/hardhat-verify": "npm:^2.0.0" + "@openzeppelin/contracts": "npm:^5.0.2" + "@typechain/ethers-v6": "npm:^0.5.0" + "@typechain/hardhat": "npm:^9.0.0" + "@types/chai": "npm:^4.2.0" + "@types/mocha": "npm:>=9.1.0" + "@types/node": "npm:>=16.0.0" + chai: "npm:^4.2.0" + eslint: "npm:^8.56.0" + eslint-graph-config: "workspace:^0.0.1" + ethers: "npm:^6.4.0" + hardhat: "npm:^2.20.1" + hardhat-contract-sizer: "npm:^2.10.0" + hardhat-gas-reporter: "npm:^1.0.8" + hardhat-storage-layout: "npm:^0.1.7" + lint-staged: "npm:^15.2.2" + prettier: "npm:^3.2.5" + prettier-plugin-solidity: "npm:^1.3.1" + solhint: "npm:^4.5.4" + solhint-graph-config: "workspace:^0.0.1" + solhint-plugin-graph: "file:node_modules/solhint-graph-config/plugin" + solidity-coverage: "npm:^0.8.0" + solidity-docgen: "npm:^0.6.0-beta.36" + ts-node: "npm:>=8.0.0" + typechain: "npm:^8.3.0" + typescript: "npm:^5.3.3" + languageName: unknown + linkType: soft + "@graphprotocol/token-distribution@workspace:packages/token-distribution": version: 0.0.0-use.local resolution: "@graphprotocol/token-distribution@workspace:packages/token-distribution" @@ -3921,7 +3945,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13, @humanwhocodes/config-array@npm:^0.11.14": +"@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: @@ -3940,9 +3964,9 @@ __metadata: linkType: hard "@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 6fd83dc320231d71c4541d0244051df61f301817e9f9da9fd4cb7e44ec8aacbde5958c1665b0c419401ab935114fdf532a6ad5d4e7294b1af2f347dd91a6983f + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: 80520eabbfc2d32fe195a93557cef50dfe8c8905de447f022675aaf66abc33ae54098f5ea78548d925aa671cd4ab7c7daa5ad704fe42358c9b5e7db60f80696c languageName: node linkType: hard @@ -3960,14 +3984,14 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" +"@jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" dependencies: - "@jridgewell/set-array": "npm:^1.0.1" + "@jridgewell/set-array": "npm:^1.2.1" "@jridgewell/sourcemap-codec": "npm:^1.4.10" - "@jridgewell/trace-mapping": "npm:^0.3.9" - checksum: 376fc11cf5a967318ba3ddd9d8e91be528eab6af66810a713c49b0c3f8dc67e9949452c51c38ab1b19aa618fb5e8594da5a249977e26b1e7fea1ee5a1fcacc74 + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 1be4fd4a6b0f41337c4f5fdf4afc3bd19e39c3691924817108b82ffcb9c9e609c273f936932b9fba4b3a298ce2eb06d9bff4eb1cc3bd81c4f4ee1b4917e25feb languageName: node linkType: hard @@ -3978,10 +4002,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: bc7ab4c4c00470de4e7562ecac3c0c84f53e7ee8a711e546d67c47da7febe7c45cd67d4d84ee3c9b2c05ae8e872656cdded8a707a283d30bd54fbc65aef821ab +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 2a5aa7b4b5c3464c895c802d8ae3f3d2b92fcbe84ad12f8d0bfbb1f5ad006717e7577ee1fd2eac00c088abe486c7adb27976f45d2941ff6b0b92b2c3302c60f4 languageName: node linkType: hard @@ -4002,13 +4026,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.22 - resolution: "@jridgewell/trace-mapping@npm:0.3.22" +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: "@jridgewell/resolve-uri": "npm:^3.1.0" "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 18cf19f88e2792c1c91515f2b629aae05f3cdbb2e60c3886e16e80725234ce26dd10144c4981c05d9366e7094498c0b4fe5c1a89f4a730d7376a4ba4af448149 + checksum: 3d1ce6ebc69df9682a5a8896b414c6537e428a1d68b02fcc8363b04284a8ca0df04d0ee3013132252ab14f2527bc13bea6526a912ecb5658f0e39fd2860b4df4 languageName: node linkType: hard @@ -4022,11 +4046,11 @@ __metadata: linkType: hard "@ljharb/through@npm:^2.3.9, @ljharb/through@npm:~2.3.9": - version: 2.3.12 - resolution: "@ljharb/through@npm:2.3.12" + version: 2.3.13 + resolution: "@ljharb/through@npm:2.3.13" dependencies: - call-bind: "npm:^1.0.5" - checksum: 7560aaef7b6ef88c16783ffde37278e2177c7f0f5427400059a8a7687b144dc711bf5b2347ab27e858a29f25e4b868d77c915c9614bc399b82b8123430614653 + call-bind: "npm:^1.0.7" + checksum: fb60b2fb2c674a674d8ebdb8972ccf52f8a62a9c1f5a2ac42557bc0273231c65d642aa2d7627cbb300766a25ae4642acd0f95fba2f8a1ff891086f0cb15807c3 languageName: node linkType: hard @@ -4115,6 +4139,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:^1.4.0": + version: 1.4.0 + resolution: "@noble/hashes@npm:1.4.0" + checksum: 8c3f005ee72e7b8f9cff756dfae1241485187254e3f743873e22073d63906863df5d4f13d441b7530ea614b7a093f0d889309f28b59850f33b66cb26a779a4a5 + languageName: node + linkType: hard + "@noble/secp256k1@npm:1.7.1, @noble/secp256k1@npm:~1.7.0": version: 1.7.1 resolution: "@noble/secp256k1@npm:1.7.1" @@ -4149,116 +4180,67 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/edr-darwin-arm64@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.2.1" - conditions: os=darwin & cpu=arm64 +"@nomicfoundation/edr-darwin-arm64@npm:0.3.8": + version: 0.3.8 + resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.3.8" + checksum: 98298ddd1dd1d513245be57dc89aad51a0ff6da2f1227c32085a8d49c0d3cbc311981539037c3030b652e1008253d6e72081f019d44cf47c6aa8f14175505554 languageName: node linkType: hard -"@nomicfoundation/edr-darwin-x64@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-darwin-x64@npm:0.2.1" - conditions: os=darwin & cpu=x64 +"@nomicfoundation/edr-darwin-x64@npm:0.3.8": + version: 0.3.8 + resolution: "@nomicfoundation/edr-darwin-x64@npm:0.3.8" + checksum: a09fb0030b5dc7e202e7d42aae9f52af86090999a50cbfd9a4b3197b9c7fc8c7325c01d67fdd88b7037a8831e0e89ecf131155edf2c98c453c28f37c6da346f4 languageName: node linkType: hard -"@nomicfoundation/edr-linux-arm64-gnu@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.2.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@nomicfoundation/edr-linux-arm64-musl@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.2.1" - conditions: os=linux & cpu=arm64 & libc=musl +"@nomicfoundation/edr-linux-arm64-gnu@npm:0.3.8": + version: 0.3.8 + resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.3.8" + checksum: 20766169cb3425202a45812f01f9e49560f7cedfb797ea548759136fb8078d6179c11557b69fab8514e7f21a3f3f856dec0ba7a1584d5b431ac1440142f2012e languageName: node linkType: hard -"@nomicfoundation/edr-linux-x64-gnu@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.2.1" - conditions: os=linux & cpu=x64 & libc=glibc +"@nomicfoundation/edr-linux-arm64-musl@npm:0.3.8": + version: 0.3.8 + resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.3.8" + checksum: dabd1ee8fc5f45382e8d58770138ba0cd6536915aa5f99459404d27dec046c76e427a0971ed705da83a6aa65e9272ac84b86b14313bd83ea4fea2c81c2d3f1e5 languageName: node linkType: hard -"@nomicfoundation/edr-linux-x64-musl@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.2.1" - conditions: os=linux & cpu=x64 & libc=musl +"@nomicfoundation/edr-linux-x64-gnu@npm:0.3.8": + version: 0.3.8 + resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.3.8" + checksum: 060aaa197a8401b0142d07042e72159703c6e61ef866e98548c00ff2512deb75d179536d63a89ce6cd0866269d22b2823459be730c2766c95b73645f7d4d1afc languageName: node linkType: hard -"@nomicfoundation/edr-win32-arm64-msvc@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-win32-arm64-msvc@npm:0.2.1" - conditions: os=win32 & cpu=arm64 +"@nomicfoundation/edr-linux-x64-musl@npm:0.3.8": + version: 0.3.8 + resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.3.8" + checksum: 49a7cb73b833a694744e2f5323d7268009eb1961e01ceb91f9137cf843e54571636b89418f204222d5f40b9122dd1c0e058b6efd368a438bc3bdb50205ea70d9 languageName: node linkType: hard -"@nomicfoundation/edr-win32-ia32-msvc@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-win32-ia32-msvc@npm:0.2.1" - conditions: os=win32 & cpu=ia32 +"@nomicfoundation/edr-win32-x64-msvc@npm:0.3.8": + version: 0.3.8 + resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.3.8" + checksum: b7dfea0f01fd034ff6b48c44f75836f4dda84975f49c3655c97e76f2535945ed532756e7f2c22fa31035c4a29ce26d9546051f993ce553a8c4d570298525f55c languageName: node linkType: hard -"@nomicfoundation/edr-win32-x64-msvc@npm:0.2.1": - version: 0.2.1 - resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.2.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@nomicfoundation/edr@npm:^0.2.0": - version: 0.2.1 - resolution: "@nomicfoundation/edr@npm:0.2.1" - dependencies: - "@nomicfoundation/edr-darwin-arm64": "npm:0.2.1" - "@nomicfoundation/edr-darwin-x64": "npm:0.2.1" - "@nomicfoundation/edr-linux-arm64-gnu": "npm:0.2.1" - "@nomicfoundation/edr-linux-arm64-musl": "npm:0.2.1" - "@nomicfoundation/edr-linux-x64-gnu": "npm:0.2.1" - "@nomicfoundation/edr-linux-x64-musl": "npm:0.2.1" - "@nomicfoundation/edr-win32-arm64-msvc": "npm:0.2.1" - "@nomicfoundation/edr-win32-ia32-msvc": "npm:0.2.1" - "@nomicfoundation/edr-win32-x64-msvc": "npm:0.2.1" - dependenciesMeta: - "@nomicfoundation/edr-darwin-arm64": - optional: true - "@nomicfoundation/edr-darwin-x64": - optional: true - "@nomicfoundation/edr-linux-arm64-gnu": - optional: true - "@nomicfoundation/edr-linux-arm64-musl": - optional: true - "@nomicfoundation/edr-linux-x64-gnu": - optional: true - "@nomicfoundation/edr-linux-x64-musl": - optional: true - "@nomicfoundation/edr-win32-arm64-msvc": - optional: true - "@nomicfoundation/edr-win32-ia32-msvc": - optional: true - "@nomicfoundation/edr-win32-x64-msvc": - optional: true - checksum: e8956284c14fb47662c92368ed17d871a24876a27c2e6525c99fabfe41cadb7d6f403889802216691ba41c38ee055c9cd59befc48f7b8018002ac2d09d2da29b - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-block@npm:4.2.2": - version: 4.2.2 - resolution: "@nomicfoundation/ethereumjs-block@npm:4.2.2" +"@nomicfoundation/edr@npm:^0.3.7": + version: 0.3.8 + resolution: "@nomicfoundation/edr@npm:0.3.8" dependencies: - "@nomicfoundation/ethereumjs-common": "npm:3.1.2" - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" - "@nomicfoundation/ethereumjs-tx": "npm:4.1.2" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - ethereum-cryptography: "npm:0.1.3" - checksum: 1c211294b3064d2bbfcf33b460438f01fb9cd77429314a90a5e2ffce5162019a384f4ae7d3825cfd386a140db191b251b475427562c53f85beffc786156f817e + "@nomicfoundation/edr-darwin-arm64": "npm:0.3.8" + "@nomicfoundation/edr-darwin-x64": "npm:0.3.8" + "@nomicfoundation/edr-linux-arm64-gnu": "npm:0.3.8" + "@nomicfoundation/edr-linux-arm64-musl": "npm:0.3.8" + "@nomicfoundation/edr-linux-x64-gnu": "npm:0.3.8" + "@nomicfoundation/edr-linux-x64-musl": "npm:0.3.8" + "@nomicfoundation/edr-win32-x64-msvc": "npm:0.3.8" + checksum: 56f4debf1d736783f498624fc2d647b075a56baedc6daf593a3e9627c99724e3fbf665245daa321a6f1db74694c11c2d70585d84fd13ecc90bf5632f503e1f04 languageName: node linkType: hard @@ -4277,40 +4259,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-block@npm:5.0.4": - version: 5.0.4 - resolution: "@nomicfoundation/ethereumjs-block@npm:5.0.4" - dependencies: - "@nomicfoundation/ethereumjs-common": "npm:4.0.4" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - ethereum-cryptography: "npm:0.1.3" - checksum: 9f8cb09f5910275188b1ad48611856c14131ad28022b958cc648f8e095fadd41002454a3396c612c2977691e59a8baad4f6adf07aab3f9c4b20b5f24c71dd7a0 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-blockchain@npm:6.2.2": - version: 6.2.2 - resolution: "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:4.2.2" - "@nomicfoundation/ethereumjs-common": "npm:3.1.2" - "@nomicfoundation/ethereumjs-ethash": "npm:2.0.5" - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - abstract-level: "npm:^1.0.3" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - level: "npm:^8.0.0" - lru-cache: "npm:^5.1.1" - memory-level: "npm:^1.0.0" - checksum: 6fe6e315900e1d6a29d59be41f566bdfd5ffdf82ab0fe081b1999dcc4eec3a248ab080d359a56e8cde4e473ca90349b0c50fa1ab707aa3e275fb1c478237e5e2 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-blockchain@npm:7.0.1": version: 7.0.1 resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.1" @@ -4332,34 +4280,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-blockchain@npm:7.0.4": - version: 7.0.4 - resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.4" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:5.0.4" - "@nomicfoundation/ethereumjs-common": "npm:4.0.4" - "@nomicfoundation/ethereumjs-ethash": "npm:3.0.4" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - lru-cache: "npm:^10.0.0" - checksum: 47f73fea07880edb68b2614981226d9315a1a3dc673d0e09d68f0bc9ebd93cbfe6ccceb3cb56f777dc9b9386cff39878349fd7474d460a38478e7175b47788f9 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-common@npm:3.1.2": - version: 3.1.2 - resolution: "@nomicfoundation/ethereumjs-common@npm:3.1.2" - dependencies: - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - crc-32: "npm:^1.2.0" - checksum: 90910630025b5bb503f36125c45395cc9f875ffdd8137a83e9c1d566678edcc8db40f8ce1dff9da1ef2c91c7d6b6d1fa75c41a9579a5d3a8f0ae669fcea244b1 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-common@npm:4.0.1": version: 4.0.1 resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.1" @@ -4379,20 +4299,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-ethash@npm:2.0.5": - version: 2.0.5 - resolution: "@nomicfoundation/ethereumjs-ethash@npm:2.0.5" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:4.2.2" - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - abstract-level: "npm:^1.0.3" - bigint-crypto-utils: "npm:^3.0.23" - ethereum-cryptography: "npm:0.1.3" - checksum: 7a90ef53ae4c1ac5a314c3447966fdbefcc96481ae3a05d59e881053350c55be7c841708c61c79a2af40bbb0181d6e0db42601592f17a4db1611b199d49e8544 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-ethash@npm:3.0.1": version: 3.0.1 resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.1" @@ -4407,35 +4313,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-ethash@npm:3.0.4": - version: 3.0.4 - resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.4" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:5.0.4" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - bigint-crypto-utils: "npm:^3.2.2" - ethereum-cryptography: "npm:0.1.3" - checksum: c4cb846b656720910fe6d4a741ad0be93833c701456da983fa3a1795dda6faaa0ab4fb3130446e648db94b68358e1e4e30024d372fb40d3f65a40650af1a83bc - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-evm@npm:1.3.2, @nomicfoundation/ethereumjs-evm@npm:^1.0.0-rc.3": - version: 1.3.2 - resolution: "@nomicfoundation/ethereumjs-evm@npm:1.3.2" - dependencies: - "@nomicfoundation/ethereumjs-common": "npm:3.1.2" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - "@types/async-eventemitter": "npm:^0.2.1" - async-eventemitter: "npm:^0.2.4" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - mcl-wasm: "npm:^0.7.1" - rustbn.js: "npm:~0.2.0" - checksum: 4aa14d7dce597a91c25bec5975022348741cebf6ed20cda028ddcbebe739ba2e6f4c879fa1ebe849bd5c78d3fd2443ebbb7d57e1fca5a98fbe88fc9ce15d9fd6 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-evm@npm:2.0.1": version: 2.0.1 resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.1" @@ -4452,31 +4329,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-evm@npm:2.0.4": - version: 2.0.4 - resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.4" - dependencies: - "@nomicfoundation/ethereumjs-common": "npm:4.0.4" - "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.4" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - "@types/debug": "npm:^4.1.9" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - rustbn-wasm: "npm:^0.2.0" - checksum: f21f4d0f1a74c903934d1c6c3abcd1342c9a812c71f142999c9f3f823119761cfdb4e89e829195fa446adb772b7f4b23ee9d55ed31bd92d5d03df438c3c29202 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-rlp@npm:4.0.3": - version: 4.0.3 - resolution: "@nomicfoundation/ethereumjs-rlp@npm:4.0.3" - bin: - rlp: bin/rlp - checksum: 3e3c07abf53ff5832afbbdf3f3687e11e2e829699348eea1ae465084c72e024559d97e351e8f0fb27f32c7896633c7dd50b19d8de486e89cde777fd5447381cd - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-rlp@npm:5.0.1": version: 5.0.1 resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.1" @@ -4495,21 +4347,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-statemanager@npm:1.0.5": - version: 1.0.5 - resolution: "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5" - dependencies: - "@nomicfoundation/ethereumjs-common": "npm:3.1.2" - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - functional-red-black-tree: "npm:^1.0.1" - checksum: 4a05b7a86a1bbc8fd409416edf437d99d9d4498c438e086c30250cb3dc92ff00086f9ff959f469c72d46178e831104dc15f10465e27fbbf0ca97da27d6889a0c - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-statemanager@npm:2.0.1": version: 2.0.1 resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.1" @@ -4524,39 +4361,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-statemanager@npm:2.0.4": - version: 2.0.4 - resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.4" - dependencies: - "@nomicfoundation/ethereumjs-common": "npm:4.0.4" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - js-sdsl: "npm:^4.1.4" - lru-cache: "npm:^10.0.0" - peerDependencies: - "@nomicfoundation/ethereumjs-verkle": 0.0.2 - peerDependenciesMeta: - "@nomicfoundation/ethereumjs-verkle": - optional: true - checksum: 6190fef25b1099ede00edf69194903a5c5df18563adae3f053e2eafacc91eeab547d257e6aa47ce7ff5264533bb7bb0fbfcb18e75ea66376ac7305ad40dafbf4 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-trie@npm:5.0.5": - version: 5.0.5 - resolution: "@nomicfoundation/ethereumjs-trie@npm:5.0.5" - dependencies: - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - ethereum-cryptography: "npm:0.1.3" - readable-stream: "npm:^3.6.0" - checksum: cab544fef4bcdc3acef1bfb4ee9f2fde44b66a22b2329bfd67515facdf115a318961f8bc0e38befded838e8fc513974f90f340b53a98b8469e54960b15cd857a - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-trie@npm:6.0.1": version: 6.0.1 resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.1" @@ -4570,32 +4374,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-trie@npm:6.0.4": - version: 6.0.4 - resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.4" - dependencies: - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - "@types/readable-stream": "npm:^2.3.13" - ethereum-cryptography: "npm:0.1.3" - lru-cache: "npm:^10.0.0" - readable-stream: "npm:^3.6.0" - checksum: b475d858f98037431c54c7177d0ce95133a81f1ee98a0b042136d65c88b7b5b3d86ba981cf78292776781d43d60daed44edf508ff4d416355bd00517e9142c9f - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-tx@npm:4.1.2": - version: 4.1.2 - resolution: "@nomicfoundation/ethereumjs-tx@npm:4.1.2" - dependencies: - "@nomicfoundation/ethereumjs-common": "npm:3.1.2" - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - ethereum-cryptography: "npm:0.1.3" - checksum: cb569c882d3ce922acff1a4238864f11109ac5a30dfa481b1ed9c7043c2b773f3a5fc88a3f4fefb62b11c448305296533f555f93d1d969a5abd3c2a13c80ed74 - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-tx@npm:5.0.1": version: 5.0.1 resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.1" @@ -4627,16 +4405,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-util@npm:8.0.6, @nomicfoundation/ethereumjs-util@npm:^8.0.0-rc.3": - version: 8.0.6 - resolution: "@nomicfoundation/ethereumjs-util@npm:8.0.6" - dependencies: - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - ethereum-cryptography: "npm:0.1.3" - checksum: 647006f4dfa962f61cec54c34ff9939468042cf762ff3b2cf80c8362558f21750348a3cda63dc9890b1cb2ba664f97dc4a892afca5f5d6f95b3ba4d56be5a33b - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-util@npm:9.0.1": version: 9.0.1 resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.1" @@ -4648,7 +4416,7 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-util@npm:9.0.4": +"@nomicfoundation/ethereumjs-util@npm:9.0.4, @nomicfoundation/ethereumjs-util@npm:^9.0.4": version: 9.0.4 resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" dependencies: @@ -4663,18 +4431,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-verkle@npm:0.0.2": - version: 0.0.2 - resolution: "@nomicfoundation/ethereumjs-verkle@npm:0.0.2" - dependencies: - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - lru-cache: "npm:^10.0.0" - rust-verkle-wasm: "npm:^0.0.1" - checksum: 7f6b3be75949adbdb8ecea4539a7c4cdce9ee1d76159b5d77f04a794e4e9de42570fc0491fc4769ecc3553547031996b16ec88ba18d68bf0e1b0d1149effb51b - languageName: node - linkType: hard - "@nomicfoundation/ethereumjs-vm@npm:7.0.1": version: 7.0.1 resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.1" @@ -4696,49 +4452,6 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-vm@npm:7.0.4": - version: 7.0.4 - resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.4" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:5.0.4" - "@nomicfoundation/ethereumjs-blockchain": "npm:7.0.4" - "@nomicfoundation/ethereumjs-common": "npm:4.0.4" - "@nomicfoundation/ethereumjs-evm": "npm:2.0.4" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.4" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - checksum: a1893c8aa0fb8666bcb7371d8a57f641bd6079a79f9e08175aca214cd4a3d7eda3e54046a7d1b4c6cbc2356e80b1e6b44295e56df2d184ceb157eb67e54ee326 - languageName: node - linkType: hard - -"@nomicfoundation/ethereumjs-vm@npm:^6.0.0-rc.3": - version: 6.4.2 - resolution: "@nomicfoundation/ethereumjs-vm@npm:6.4.2" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:4.2.2" - "@nomicfoundation/ethereumjs-blockchain": "npm:6.2.2" - "@nomicfoundation/ethereumjs-common": "npm:3.1.2" - "@nomicfoundation/ethereumjs-evm": "npm:1.3.2" - "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" - "@nomicfoundation/ethereumjs-statemanager": "npm:1.0.5" - "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" - "@nomicfoundation/ethereumjs-tx": "npm:4.1.2" - "@nomicfoundation/ethereumjs-util": "npm:8.0.6" - "@types/async-eventemitter": "npm:^0.2.1" - async-eventemitter: "npm:^0.2.4" - debug: "npm:^4.3.3" - ethereum-cryptography: "npm:0.1.3" - functional-red-black-tree: "npm:^1.0.1" - mcl-wasm: "npm:^0.7.1" - rustbn.js: "npm:~0.2.0" - checksum: 78e4b0ba20e8fa4ef112bae88f432746647ed48b41918b34855fe08269be3aaff84f95c08b6c61475fb70f24a28ba73612bd2bcd19b3c007c8bf9e11a43fa8e0 - languageName: node - linkType: hard - "@nomicfoundation/hardhat-chai-matchers@npm:^2.0.0": version: 2.0.6 resolution: "@nomicfoundation/hardhat-chai-matchers@npm:2.0.6" @@ -4757,26 +4470,26 @@ __metadata: linkType: hard "@nomicfoundation/hardhat-ethers@npm:^3.0.0": - version: 3.0.5 - resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.5" + version: 3.0.6 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.6" dependencies: debug: "npm:^4.1.1" lodash.isequal: "npm:^4.5.0" peerDependencies: ethers: ^6.1.0 hardhat: ^2.0.0 - checksum: 8253d107f956fbbfcb55b758cfd05159dcc77289bc115418626c3be32efeaced82c7dbfcb9d67ef0d9dccb6851e8588edeb228f325982ac3c61d7f605bcef009 + checksum: c7abe4234fae6422a357ef9e959cfe4183d5d7121d18e9f71b1659944419fde7d2a0290cd42fd5e85d855d8c83b86bbaed316f4950f0976015f941d958679a99 languageName: node linkType: hard "@nomicfoundation/hardhat-foundry@npm:^1.1.1": - version: 1.1.1 - resolution: "@nomicfoundation/hardhat-foundry@npm:1.1.1" + version: 1.1.2 + resolution: "@nomicfoundation/hardhat-foundry@npm:1.1.2" dependencies: chalk: "npm:^2.4.2" peerDependencies: hardhat: ^2.17.2 - checksum: e1f914bd705b93c9efc9f0b30eb178288504aede202ec00a9b03d3fa494baf175d0218ee678a328179b1ecfe18e16184888f671e8a03488e4ebfba0daf93a603 + checksum: 54cad1a0d1fc3c2137722a1b213dcbd18f77e63778bda9593052e6090868b2fb7bf8087c10404c6b181fa631e75f7e70490b5b97c3e4eba8f52ef449131dada0 languageName: node linkType: hard @@ -4817,8 +4530,8 @@ __metadata: linkType: hard "@nomicfoundation/hardhat-verify@npm:^2.0.0": - version: 2.0.4 - resolution: "@nomicfoundation/hardhat-verify@npm:2.0.4" + version: 2.0.7 + resolution: "@nomicfoundation/hardhat-verify@npm:2.0.7" dependencies: "@ethersproject/abi": "npm:^5.1.2" "@ethersproject/address": "npm:^5.0.2" @@ -4831,7 +4544,7 @@ __metadata: undici: "npm:^5.14.0" peerDependencies: hardhat: ^2.0.4 - checksum: 9003db2eb06aad8764473240d5ddb0cdef27b9bd7ed4586469aec8997d4556a1b1f11c537b567e3a30af694ac5d756dc9cccc52c14604e92d0dfdc964d12c6e8 + checksum: a6b3b89d3d2a594c44b50832840deefd3261b158bde774319322859077637f656c2e436af21ca3ce10d60eac78e3a1fbfea02abfe20a4729f97b4f30515524a6 languageName: node linkType: hard @@ -5003,24 +4716,24 @@ __metadata: linkType: hard "@npmcli/agent@npm:^2.0.0": - version: 2.2.1 - resolution: "@npmcli/agent@npm:2.2.1" + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" dependencies: agent-base: "npm:^7.1.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.1" lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.1" - checksum: 38ee5cbe8f3cde13be916e717bfc54fd1a7605c07af056369ff894e244c221e0b56b08ca5213457477f9bc15bca9e729d51a4788829b5c3cf296b3c996147f76 + socks-proxy-agent: "npm:^8.0.3" + checksum: 325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae languageName: node linkType: hard "@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" dependencies: semver: "npm:^7.3.5" - checksum: 162b4a0b8705cd6f5c2470b851d1dc6cd228c86d2170e1769d738c1fbb69a87160901411c3c035331e9e99db72f1f1099a8b734bf1637cc32b9a5be1660e4e1e + checksum: c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 languageName: node linkType: hard @@ -5053,28 +4766,28 @@ __metadata: linkType: hard "@openzeppelin/defender-admin-client@npm:^1.46.0": - version: 1.54.1 - resolution: "@openzeppelin/defender-admin-client@npm:1.54.1" + version: 1.54.2 + resolution: "@openzeppelin/defender-admin-client@npm:1.54.2" dependencies: - "@openzeppelin/defender-base-client": "npm:1.54.1" + "@openzeppelin/defender-base-client": "npm:1.54.2" axios: "npm:^1.4.0" ethers: "npm:^5.7.2" lodash: "npm:^4.17.19" node-fetch: "npm:^2.6.0" - checksum: b8d9b112bc9c477aca23a9b7249801eb997295302afe60e5c0883579f1ca1069a411ee7be9f972de52019bf59e0d36b7c11503ec09d4328c15899fa4bfdf6d6c + checksum: fff2a74f840168d65a7cc51992610c199eb0d2b54b63f84060dded898d2730e0b008b3f492251ec99a697d45e69987a203ee005b5912e51a2786407755e3e53f languageName: node linkType: hard -"@openzeppelin/defender-base-client@npm:1.54.1, @openzeppelin/defender-base-client@npm:^1.46.0": - version: 1.54.1 - resolution: "@openzeppelin/defender-base-client@npm:1.54.1" +"@openzeppelin/defender-base-client@npm:1.54.2, @openzeppelin/defender-base-client@npm:^1.46.0": + version: 1.54.2 + resolution: "@openzeppelin/defender-base-client@npm:1.54.2" dependencies: amazon-cognito-identity-js: "npm:^6.0.1" async-retry: "npm:^1.3.3" axios: "npm:^1.4.0" lodash: "npm:^4.17.19" node-fetch: "npm:^2.6.0" - checksum: 10a709dfc4fc55ad8d431b1c6d5e67129131d9763f3a91b9ec9ee63653cc8b0a8567809d04341bcb8615e0e20c917c2045a45693070ee9d83da11620338d874d + checksum: b30c5c5ed47ed0ff788025abd0cdfc816fdbd49065c221be7e760385e5cbf5b05488ed1cfb040c5cbe0a1ca6cc6af035dc88a6e5b2c09fb9ae4ae048493014bd languageName: node linkType: hard @@ -5128,8 +4841,8 @@ __metadata: linkType: hard "@openzeppelin/upgrades-core@npm:^1.27.0": - version: 1.32.5 - resolution: "@openzeppelin/upgrades-core@npm:1.32.5" + version: 1.33.1 + resolution: "@openzeppelin/upgrades-core@npm:1.33.1" dependencies: cbor: "npm:^9.0.0" chalk: "npm:^4.1.0" @@ -5141,7 +4854,7 @@ __metadata: solidity-ast: "npm:^0.4.51" bin: openzeppelin-upgrades-core: dist/cli/cli.js - checksum: aac654c46aadcfba55024a17d029edcbc529be2fae16fa8d4efc3fd8114cbb4d36d8974a62b1f34fcfa593b3b072898995034ff3bb6a921e00bcac669d8b1998 + checksum: 96fbed78baec7502709a38f5a00180750c24e96aa047a438b34c0d9895dc4ffed47b7e4fedab57cabfd733a3c079e78c98eec23a6df61f3fb4c8b2c9d096bcba languageName: node linkType: hard @@ -5166,15 +4879,15 @@ __metadata: linkType: hard "@peculiar/webcrypto@npm:^1.4.0": - version: 1.4.5 - resolution: "@peculiar/webcrypto@npm:1.4.5" + version: 1.4.6 + resolution: "@peculiar/webcrypto@npm:1.4.6" dependencies: "@peculiar/asn1-schema": "npm:^2.3.8" "@peculiar/json-schema": "npm:^1.1.12" pvtsutils: "npm:^1.3.5" tslib: "npm:^2.6.2" - webcrypto-core: "npm:^1.7.8" - checksum: 7cefe2a1329e3d41721268cf483dfd7a7a3bfbdaaba0ca8db9a538b49a51c6977f66f7f85e6f0c2162ff8d09540821bedc6766586d83c4be565b1af49ea81a86 + webcrypto-core: "npm:^1.7.9" + checksum: b9c80b1a0a3e3ebbf045bd5167fe99ec4a83b170e9aa15a5952a9138afc278210d772306dcc57101d9407c3f9c70dbf6bfb4d8b3f20996ad35c650bb0fe6a90c languageName: node linkType: hard @@ -5236,9 +4949,9 @@ __metadata: linkType: hard "@repeaterjs/repeater@npm:^3.0.4": - version: 3.0.5 - resolution: "@repeaterjs/repeater@npm:3.0.5" - checksum: e6e1aca2bbfe0b8e974bc5185a6839f9e78ec8acb96b6d6911a9dfc958443689f9bc38bcc6d554e6c8598f597f0151841aafbd1ee3ef16262ee93d18b2c1d4b5 + version: 3.0.6 + resolution: "@repeaterjs/repeater@npm:3.0.6" + checksum: c3915e2603927c7d6a9eb09673bc28fc49ab3a86947ec191a74663b33deebee2fcc4b03c31cc663ff27bd6db9e6c9487639b6935e265d601ce71b8c497f5f4a8 languageName: node linkType: hard @@ -5329,10 +5042,10 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.1.1, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.4": - version: 1.1.5 - resolution: "@scure/base@npm:1.1.5" - checksum: 6eb07be0202fac74a57c79d0d00a45f6f7e57447010c1e3d90a4275d197829727b7abc54b248fc6f9bef9ae374f7be5ee9154dde5b5b73da773560bf17aa8504 +"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.4": + version: 1.1.6 + resolution: "@scure/base@npm:1.1.6" + checksum: 237a46a1f45391fc57719154f14295db936a0b1562ea3e182dd42d7aca082dbb7062a28d6c49af16a7e478b12dae8a0fe678d921ea5056bcc30238d29eb05c55 languageName: node linkType: hard @@ -5481,12 +5194,12 @@ __metadata: languageName: node linkType: hard -"@smithy/types@npm:^2.9.1": - version: 2.10.0 - resolution: "@smithy/types@npm:2.10.0" +"@smithy/types@npm:^3.0.0": + version: 3.0.0 + resolution: "@smithy/types@npm:3.0.0" dependencies: - tslib: "npm:^2.5.0" - checksum: e82d7584e9b0d0c8fb6da059af6ebcb8af86dba7c1dc3e757b4998eca636f8dd697ea47701ff6c755789f0a63ef16f960fcc682ab2ca185cef4c6a6db5f022dc + tslib: "npm:^2.6.2" + checksum: 9f6eefa4f715a8f0bfd79787f82156b4785baaa1524496abe9fc3db96c36f7c782fb962353601d8bd2bba3b449d999d48a09b2b25405bfcd7fb5e1d1c935f1fb languageName: node linkType: hard @@ -5522,72 +5235,72 @@ __metadata: languageName: node linkType: hard -"@stylistic/eslint-plugin-js@npm:1.6.2, @stylistic/eslint-plugin-js@npm:^1.6.2": - version: 1.6.2 - resolution: "@stylistic/eslint-plugin-js@npm:1.6.2" +"@stylistic/eslint-plugin-js@npm:1.8.1, @stylistic/eslint-plugin-js@npm:^1.8.1": + version: 1.8.1 + resolution: "@stylistic/eslint-plugin-js@npm:1.8.1" dependencies: - "@types/eslint": "npm:^8.56.2" + "@types/eslint": "npm:^8.56.10" acorn: "npm:^8.11.3" escape-string-regexp: "npm:^4.0.0" eslint-visitor-keys: "npm:^3.4.3" espree: "npm:^9.6.1" peerDependencies: eslint: ">=8.40.0" - checksum: b74b08802cb888b64b2432e2fa7723c664d1b6a3ee5ad48f8caeef83eebcfcf291f92f967b65e79854d19a660e9428567247de402eeb9e59d9320f71c8c3881e + checksum: 0f5aa5f4afd0a0120a7675f5f0abb2d6fc5ee6197390613a69dcf510644964f1eb8ef8c060be2cf8c1885863a507bdf42e74954f886dca4102e49acfee50c577 languageName: node linkType: hard -"@stylistic/eslint-plugin-jsx@npm:1.6.2": - version: 1.6.2 - resolution: "@stylistic/eslint-plugin-jsx@npm:1.6.2" +"@stylistic/eslint-plugin-jsx@npm:1.8.1": + version: 1.8.1 + resolution: "@stylistic/eslint-plugin-jsx@npm:1.8.1" dependencies: - "@stylistic/eslint-plugin-js": "npm:^1.6.2" - "@types/eslint": "npm:^8.56.2" + "@stylistic/eslint-plugin-js": "npm:^1.8.1" + "@types/eslint": "npm:^8.56.10" estraverse: "npm:^5.3.0" - picomatch: "npm:^4.0.1" + picomatch: "npm:^4.0.2" peerDependencies: eslint: ">=8.40.0" - checksum: 882daa8ac9e3d7db5009dd6a9b4c406edab0ced233d3d49e6a9a0acb94ed68d8e5ec9a705c8925c7adc103ef9c057f33b74c32c7087f40a61c5b85f31f530fcc + checksum: 3bf9a543c1dc661bbe1fb939a46a8cc9543f8c2fbd53b39c05861e042e28c7483cf318152c5cbf1dbc6022e0e211375931f707c5d9a7a63f83a74f857f7b28b4 languageName: node linkType: hard -"@stylistic/eslint-plugin-plus@npm:1.6.2": - version: 1.6.2 - resolution: "@stylistic/eslint-plugin-plus@npm:1.6.2" +"@stylistic/eslint-plugin-plus@npm:1.8.1": + version: 1.8.1 + resolution: "@stylistic/eslint-plugin-plus@npm:1.8.1" dependencies: - "@types/eslint": "npm:^8.56.2" + "@types/eslint": "npm:^8.56.10" "@typescript-eslint/utils": "npm:^6.21.0" peerDependencies: eslint: "*" - checksum: 426e68c7edcb96d48f8ccb22c07fb5b7b26d85210494cfbafb6331d67496946ae3af841933059c31594d5f7c8b4e867de2345418d64a1885b102988d7679fae1 + checksum: 644cf23179b69df12bc798357ae0193eed2dd68a6e5e8dd11f5c8ecad0898eb58b5dac68fafd31c52b852b0800cb21ce457397d4d94cb60549311283540a2dd4 languageName: node linkType: hard -"@stylistic/eslint-plugin-ts@npm:1.6.2": - version: 1.6.2 - resolution: "@stylistic/eslint-plugin-ts@npm:1.6.2" +"@stylistic/eslint-plugin-ts@npm:1.8.1": + version: 1.8.1 + resolution: "@stylistic/eslint-plugin-ts@npm:1.8.1" dependencies: - "@stylistic/eslint-plugin-js": "npm:1.6.2" - "@types/eslint": "npm:^8.56.2" + "@stylistic/eslint-plugin-js": "npm:1.8.1" + "@types/eslint": "npm:^8.56.10" "@typescript-eslint/utils": "npm:^6.21.0" peerDependencies: eslint: ">=8.40.0" - checksum: 15e19abfce7ac77843d1331ee5cab74b405bdb5fb890acb071f6a7c21dc81b338d6482f227aa0af0b32faa61de25166b3a3253cec1df867f99ca105155e001cc + checksum: 1bd0bb220998b7ebd3a7e788b8bafc6674291160604825eea547cfd1a9530b02777ffe5775ddce932388044d7e932c9693be8c30fa989b03ee0ddf98ebc3d40d languageName: node linkType: hard "@stylistic/eslint-plugin@npm:^1.6.2": - version: 1.6.2 - resolution: "@stylistic/eslint-plugin@npm:1.6.2" + version: 1.8.1 + resolution: "@stylistic/eslint-plugin@npm:1.8.1" dependencies: - "@stylistic/eslint-plugin-js": "npm:1.6.2" - "@stylistic/eslint-plugin-jsx": "npm:1.6.2" - "@stylistic/eslint-plugin-plus": "npm:1.6.2" - "@stylistic/eslint-plugin-ts": "npm:1.6.2" - "@types/eslint": "npm:^8.56.2" + "@stylistic/eslint-plugin-js": "npm:1.8.1" + "@stylistic/eslint-plugin-jsx": "npm:1.8.1" + "@stylistic/eslint-plugin-plus": "npm:1.8.1" + "@stylistic/eslint-plugin-ts": "npm:1.8.1" + "@types/eslint": "npm:^8.56.10" peerDependencies: eslint: ">=8.40.0" - checksum: 353c852e1ace9b80bfe18a31b977723d79081397a12ebd14f34f2f5c2eeebc71a38ea17b65b9e3e3d8fcf09c14807822bf9123551e8df1785a3d1d1a6ee39c51 + checksum: 036e4e9dcc4674810bd36b22404234b6a34b79b762fe8275470916ce5a3d3b10e5ef9ba86fb786fcbb39b801a6757079915c1cdd57d07c88ed472fdff5192cc4 languageName: node linkType: hard @@ -5681,9 +5394,9 @@ __metadata: linkType: hard "@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: c176a2c1e1b16be120c328300ea910df15fb9a5277010116d26818272341a11483c5a80059389d04edacf6fd2d03d4687ad3660870fdd1cc0b7109e160adb220 + version: 1.0.11 + resolution: "@tsconfig/node10@npm:1.0.11" + checksum: 28a0710e5d039e0de484bdf85fee883bfd3f6a8980601f4d44066b0a6bcd821d31c4e231d1117731c4e24268bd4cf2a788a6787c12fc7f8d11014c07d582783c languageName: node linkType: hard @@ -5808,15 +5521,6 @@ __metadata: languageName: node linkType: hard -"@types/async-eventemitter@npm:^0.2.1": - version: 0.2.4 - resolution: "@types/async-eventemitter@npm:0.2.4" - dependencies: - "@types/events": "npm:*" - checksum: 2ae267eb3e959fe5aaf6d850ab06ac2e5b44f1a7e3e421250f3ebaa8a108f641e9050d042980bc35aab98d6fa5f1a62a43cfb7f377011ce9013ed62229327111 - languageName: node - linkType: hard - "@types/bn.js@npm:*, @types/bn.js@npm:^5.1.0, @types/bn.js@npm:^5.1.1": version: 5.1.5 resolution: "@types/bn.js@npm:5.1.5" @@ -5867,9 +5571,9 @@ __metadata: linkType: hard "@types/chai@npm:*, @types/chai@npm:^4.2.0, @types/chai@npm:^4.3.9": - version: 4.3.12 - resolution: "@types/chai@npm:4.3.12" - checksum: e5d952726d7f053812579962b07d0e4965c160c6a90bf466580e639cd3a1f1d30da1abbfe782383538a043a07908f9dfb823fa9065b37752a5f27d62234f44d5 + version: 4.3.16 + resolution: "@types/chai@npm:4.3.16" + checksum: 745d4a9be429d5d86a7ab26064610b8957fe12dd80e94dc7d0707cf3db1c889e3ffe0d73d69bb15e6d376bf4462a7a75e9d8fc1051750b5d656d6cfe459829b7 languageName: node linkType: hard @@ -5882,7 +5586,7 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:^4.1.10, @types/debug@npm:^4.1.7, @types/debug@npm:^4.1.8, @types/debug@npm:^4.1.9": +"@types/debug@npm:^4.1.10, @types/debug@npm:^4.1.7, @types/debug@npm:^4.1.8": version: 4.1.12 resolution: "@types/debug@npm:4.1.12" dependencies: @@ -5900,13 +5604,13 @@ __metadata: languageName: node linkType: hard -"@types/eslint@npm:*, @types/eslint@npm:^8.56.2": - version: 8.56.3 - resolution: "@types/eslint@npm:8.56.3" +"@types/eslint@npm:*, @types/eslint@npm:^8.56.10": + version: 8.56.10 + resolution: "@types/eslint@npm:8.56.10" dependencies: "@types/estree": "npm:*" "@types/json-schema": "npm:*" - checksum: c5d81d0001fae211451b39d82b2bc8d7224b00d52a514954a33840a3665f36f3bde3be602eec6ad08d1fff59108052cd7746ced4237116bc3d8ac01a7cf5b5fe + checksum: 674349d6c342c3864d70f4d5a9965f96fb253801532752c8c500ad6a1c2e8b219e01ccff5dc8791dcb58b5483012c495708bb9f3ff929f5c9322b3da126c15d3 languageName: node linkType: hard @@ -5926,13 +5630,6 @@ __metadata: languageName: node linkType: hard -"@types/events@npm:*": - version: 3.0.3 - resolution: "@types/events@npm:3.0.3" - checksum: 3a56f8c51eb4ebc0d05dcadca0c6636c816acc10216ce36c976fad11e54a01f4bb979a07211355686015884753b37f17d74bfdc7aaf4ebb027c1e8a501c7b21d - languageName: node - linkType: hard - "@types/form-data@npm:0.0.33": version: 0.0.33 resolution: "@types/form-data@npm:0.0.33" @@ -5996,9 +5693,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.200": - version: 4.14.202 - resolution: "@types/lodash@npm:4.14.202" - checksum: 6064d43c8f454170841bd67c8266cc9069d9e570a72ca63f06bceb484cb4a3ee60c9c1f305c1b9e3a87826049fd41124b8ef265c4dd08b00f6766609c7fe9973 + version: 4.17.4 + resolution: "@types/lodash@npm:4.17.4" + checksum: 0124c64cb9fe7a0f78b6777955abd05ef0d97844d49118652eae45f8fa57bfb7f5a7a9bccc0b5a84c0a6dc09631042e4590cb665acb9d58dfd5e6543c75341ec languageName: node linkType: hard @@ -6070,37 +5767,19 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.11.19, @types/node@npm:^20.4.2, @types/node@npm:^20.8.7, @types/node@npm:^20.9.0": - version: 20.11.20 - resolution: "@types/node@npm:20.11.20" - dependencies: - undici-types: "npm:~5.26.4" - checksum: 8e8de211e6d54425c603388a9b5cc9c434101985d0a1c88aabbf65d10df2b1fccd71855c20e61ae8a75c7aea56cb0f64e722cf7914cff1247d0b62ce21996ac4 - languageName: node - linkType: hard - -"@types/node@npm:18.15.13": - version: 18.15.13 - resolution: "@types/node@npm:18.15.13" - checksum: 6e5f61c559e60670a7a8fb88e31226ecc18a21be103297ca4cf9848f0a99049dae77f04b7ae677205f2af494f3701b113ba8734f4b636b355477a6534dbb8ada - languageName: node - linkType: hard - -"@types/node@npm:>=12": - version: 20.11.30 - resolution: "@types/node@npm:20.11.30" +"@types/node@npm:*, @types/node@npm:>=12, @types/node@npm:>=16.0.0, @types/node@npm:^20.11.19, @types/node@npm:^20.4.2, @types/node@npm:^20.8.7, @types/node@npm:^20.9.0": + version: 20.12.12 + resolution: "@types/node@npm:20.12.12" dependencies: undici-types: "npm:~5.26.4" - checksum: 867cfaf969c6d8850d8d7304e7ab739898a50ecb1395b61ff2335644f5f48d7a46fbc4a14cee967aed65ec134b61a746edae70d1f32f11321ccf29165e3bc4e6 + checksum: f374b763c744e8f16e4f38cf6e2c0eef31781ec9228c9e43a6f267880fea420fab0a238b59f10a7cb3444e49547c5e3785787e371fc242307310995b21988812 languageName: node linkType: hard -"@types/node@npm:>=16.0.0": - version: 20.11.26 - resolution: "@types/node@npm:20.11.26" - dependencies: - undici-types: "npm:~5.26.4" - checksum: 2df81e4f109588c4c490f2c7d616a06d2b3b9298f217468134b80711af810c9a6017a59beb3e6b1c596eb9b6c5a39d33403b99179acb89006badfbc55f2468bb +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: 6e5f61c559e60670a7a8fb88e31226ecc18a21be103297ca4cf9848f0a99049dae77f04b7ae677205f2af494f3701b113ba8734f4b636b355477a6534dbb8ada languageName: node linkType: hard @@ -6162,17 +5841,10 @@ __metadata: languageName: node linkType: hard -"@types/qs@npm:^6.2.31, @types/qs@npm:^6.9.4": - version: 6.9.11 - resolution: "@types/qs@npm:6.9.11" - checksum: 657a50f05b694d6fd3916d24177cfa0f3b8b87d9deff4ffa4dddcb0b03583ebf7c47b424b8de400270fb9a5cc1e9cf790dd82c833c6935305851e7da8ede3ff5 - languageName: node - linkType: hard - -"@types/qs@npm:^6.9.7": - version: 6.9.13 - resolution: "@types/qs@npm:6.9.13" - checksum: 0e2dbfb6ee13657cd87742f92c94f1b7a70901452fce477fb9391928165766623581a3229b34fde3e832afbedee509de98984124f38b513ba072d6e193ea06cd +"@types/qs@npm:^6.2.31, @types/qs@npm:^6.9.4, @types/qs@npm:^6.9.7": + version: 6.9.15 + resolution: "@types/qs@npm:6.9.15" + checksum: 49c5ff75ca3adb18a1939310042d273c9fc55920861bd8e5100c8a923b3cda90d759e1a95e18334092da1c8f7b820084687770c83a1ccef04fb2c6908117c823 languageName: node linkType: hard @@ -6214,9 +5886,9 @@ __metadata: linkType: hard "@types/semver@npm:^7.5.0": - version: 7.5.7 - resolution: "@types/semver@npm:7.5.7" - checksum: fb72d8b86a7779650f14ae89542f1da2ab624adb8188d98754b1d29a2fe3d41f0348bf9435b60ad145df1812fd2a09b3256779aa23b532c199f3dee59619a1eb + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: 8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa languageName: node linkType: hard @@ -6270,9 +5942,9 @@ __metadata: linkType: hard "@types/validator@npm:^13.7.1, @types/validator@npm:^13.7.17": - version: 13.11.9 - resolution: "@types/validator@npm:13.11.9" - checksum: 856ebfcfe25d6c91a90235e0eb27302a737832530898195bbfb265da52ae7fe6d68f684942574f8818d3c262cae7a1de99f145dac73fc57217933af1bfc199cb + version: 13.11.10 + resolution: "@types/validator@npm:13.11.10" + checksum: fe63a20fa90d3e8c661d0ac5b5af162cdd387b9e8fd67f5a0a00ca308e4e2d7602467cc32ef3e2c979b737629fa9e2ff593d3946ee4f8667bbb80af0494b9c66 languageName: node linkType: hard @@ -6320,28 +5992,26 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/eslint-plugin@npm:7.0.2" +"@typescript-eslint/eslint-plugin@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.9.0" dependencies: - "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:7.0.2" - "@typescript-eslint/type-utils": "npm:7.0.2" - "@typescript-eslint/utils": "npm:7.0.2" - "@typescript-eslint/visitor-keys": "npm:7.0.2" - debug: "npm:^4.3.4" + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:7.9.0" + "@typescript-eslint/type-utils": "npm:7.9.0" + "@typescript-eslint/utils": "npm:7.9.0" + "@typescript-eslint/visitor-keys": "npm:7.9.0" graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.4" + ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + ts-api-utils: "npm:^1.3.0" peerDependencies: "@typescript-eslint/parser": ^7.0.0 eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 76727ad48f01c1bb4ef37690e7ed12754930ce3a4bbe5dcd52f24d42f4625fc0b151db8189947f3956b4a09a562eb2da683ff65b57a13a15426eee3b680f80a5 + checksum: 5c0ded9cb2210c141d236075f01a86447bf497a5061773c3c64a90756264776b4c4df100f7588e36d34f727eca55afd52fe6696a3cbe2d1f131250934254603a languageName: node linkType: hard @@ -6370,21 +6040,21 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/parser@npm:7.0.2" +"@typescript-eslint/parser@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/parser@npm:7.9.0" dependencies: - "@typescript-eslint/scope-manager": "npm:7.0.2" - "@typescript-eslint/types": "npm:7.0.2" - "@typescript-eslint/typescript-estree": "npm:7.0.2" - "@typescript-eslint/visitor-keys": "npm:7.0.2" + "@typescript-eslint/scope-manager": "npm:7.9.0" + "@typescript-eslint/types": "npm:7.9.0" + "@typescript-eslint/typescript-estree": "npm:7.9.0" + "@typescript-eslint/visitor-keys": "npm:7.9.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: acffdbea0bba24398ba8bd1ccf5b59438bc093e41d7a325019383094f39d676b5cf2f5963bfa5e332e54728e5b9e14be3984752ee91da6f0e1a3e0b613422d0e + checksum: 16ca04645429436d9b7986cddda979ef4d088f4223f4a69e04a369e0fd4852dd5ff3d4b99da2e43cddaa2b421b24ff42f275d87bd110ae2356bdd0e81c2534e7 languageName: node linkType: hard @@ -6416,13 +6086,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/scope-manager@npm:7.0.2" +"@typescript-eslint/scope-manager@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/scope-manager@npm:7.9.0" dependencies: - "@typescript-eslint/types": "npm:7.0.2" - "@typescript-eslint/visitor-keys": "npm:7.0.2" - checksum: 60241a0dbed7605133b6242d7fc172e8ee649e1033b8a179cebe3e21c60e0c08c12679fd37644cfef57c95a5d75a3927afc9d6365a5f9684c1d043285db23c66 + "@typescript-eslint/types": "npm:7.9.0" + "@typescript-eslint/visitor-keys": "npm:7.9.0" + checksum: 1ba6fc559a42a9b54e38c3ac2b6669efcff1a30292fb4e5fc8739c890a6c0f37d1a6aee1d115198f57c88e4f1776e95c1d7143de5cb5b970d5eb3023e97789dd languageName: node linkType: hard @@ -6443,20 +6113,20 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/type-utils@npm:7.0.2" +"@typescript-eslint/type-utils@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/type-utils@npm:7.9.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:7.0.2" - "@typescript-eslint/utils": "npm:7.0.2" + "@typescript-eslint/typescript-estree": "npm:7.9.0" + "@typescript-eslint/utils": "npm:7.9.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^1.0.1" + ts-api-utils: "npm:^1.3.0" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: fa7957aa65cb0d7366c7c9be94e45cc2f1ebe9981cbf393054b505c6d555a01b2a2fe7cd1254d668f30183a275032f909186ce0b9f213f64b776bd7872144a6e + checksum: 775280fb179268f8bacd60e684d9d5a1c6a379646b082c7244bf2dfb7dd693053bd9efa473b71e10a86db69322b0a2cecf5598d019684930df50000bf3d70af0 languageName: node linkType: hard @@ -6467,10 +6137,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/types@npm:7.0.2" - checksum: 5f95266cc2cd0e6cf1239dcd36b53c7d98b01ba12c61947316f0d879df87b912b4d23f0796324e2ab0fb8780503a338da41a4695fa91d90392b6c6aca5239fa7 +"@typescript-eslint/types@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/types@npm:7.9.0" + checksum: d5f4a547dba4865ee2391bf06f2b3f8e8592a561976d2be35bb61ce340c7d1b7b4b25ac6ab5b9941813b465b9420bebb7b2179b1d71f6a83069feeb000b3558d languageName: node linkType: hard @@ -6493,22 +6163,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/typescript-estree@npm:7.0.2" +"@typescript-eslint/typescript-estree@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.9.0" dependencies: - "@typescript-eslint/types": "npm:7.0.2" - "@typescript-eslint/visitor-keys": "npm:7.0.2" + "@typescript-eslint/types": "npm:7.9.0" + "@typescript-eslint/visitor-keys": "npm:7.9.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" - minimatch: "npm:9.0.3" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 2f6795b05fced9f2e0887f6735aa1a0b20516952792e4be13cd94c5e56db8ad013ba27aeb56f89fedff8b7af587f854482f00aac75b418611c74e42169c29aeb + checksum: cfc3d2b7a5433c9a2989c7289bc72b49786993782801ad8ca5a07c651df457a67fbce13b120c86c34c03d56570a90e5cf4f3b8806349f103a3658f2366ec28ea languageName: node linkType: hard @@ -6529,20 +6199,17 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/utils@npm:7.0.2" +"@typescript-eslint/utils@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/utils@npm:7.9.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@types/json-schema": "npm:^7.0.12" - "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:7.0.2" - "@typescript-eslint/types": "npm:7.0.2" - "@typescript-eslint/typescript-estree": "npm:7.0.2" - semver: "npm:^7.5.4" + "@typescript-eslint/scope-manager": "npm:7.9.0" + "@typescript-eslint/types": "npm:7.9.0" + "@typescript-eslint/typescript-estree": "npm:7.9.0" peerDependencies: eslint: ^8.56.0 - checksum: b4ae9a36393c92b332e99d70219d1ee056271261f7433924db804e5f06d97ca60408b9c7a655afce8a851982e7153243a625d6cc76fea764f767f96c8f3e16da + checksum: cb99d6a950e7da0319bc7b923a82c52c0798a14e837afee51b2295cfbde02e0a2ac8e0b5904cd7bd01d1b376c7a6ad3739101b486feaf2517c8640024deb88c7 languageName: node linkType: hard @@ -6556,13 +6223,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.0.2": - version: 7.0.2 - resolution: "@typescript-eslint/visitor-keys@npm:7.0.2" +"@typescript-eslint/visitor-keys@npm:7.9.0": + version: 7.9.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.9.0" dependencies: - "@typescript-eslint/types": "npm:7.0.2" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 4146d1ad6ce9374e6b5a75677fc709816bdc5fe324b1a857405f21dad23bb28c79cfd0555bc2a01c4af1d9e9ee81ff5e29ec41cc9d05b0b1101cc4264e7f21d1 + "@typescript-eslint/types": "npm:7.9.0" + eslint-visitor-keys: "npm:^3.4.3" + checksum: 19181d8b9d2d7bc43d5c8884661cd9a86ac316392b8e590187cc507442093a1ba2bef0cc22181b8298d5dc9f455abb73cffa4663451bdf32b1b7fe12160c5c99 languageName: node linkType: hard @@ -6586,12 +6253,12 @@ __metadata: linkType: hard "@urql/core@npm:>=2.3.6": - version: 4.2.3 - resolution: "@urql/core@npm:4.2.3" + version: 5.0.3 + resolution: "@urql/core@npm:5.0.3" dependencies: - "@0no-co/graphql.web": "npm:^1.0.1" + "@0no-co/graphql.web": "npm:^1.0.5" wonka: "npm:^6.3.2" - checksum: 2e2e5f94365c5513c6eb8d996d0b60211ca5ef122bfb7e77a192f63f8f469689ead2b232b835ce47f8127d7c9a5c8083548cac05f3b4be4f01f723dbfb575da0 + checksum: 7ae9dfe4cbce949a0e2856f46e5c0f62a1bdb6eda6f24480468b62f886cc03131e77b578da4fbb9fe8c1622b7542fdd371b83e7883f01a296924b5dfbe738f10 languageName: node linkType: hard @@ -6872,12 +6539,12 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: "npm:^4.3.4" - checksum: fc974ab57ffdd8421a2bc339644d312a9cca320c20c3393c9d8b1fd91731b9bbabdb985df5fc860f5b79d81c3e350daa3fcb31c5c07c0bb385aafc817df004ce + checksum: e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 languageName: node linkType: hard @@ -6930,27 +6597,27 @@ __metadata: linkType: hard "ajv@npm:^8.0.0, ajv@npm:^8.0.1, ajv@npm:^8.11.0, ajv@npm:^8.12.0": - version: 8.12.0 - resolution: "ajv@npm:8.12.0" + version: 8.13.0 + resolution: "ajv@npm:8.13.0" dependencies: - fast-deep-equal: "npm:^3.1.1" + fast-deep-equal: "npm:^3.1.3" json-schema-traverse: "npm:^1.0.0" require-from-string: "npm:^2.0.2" - uri-js: "npm:^4.2.2" - checksum: ac4f72adf727ee425e049bc9d8b31d4a57e1c90da8d28bcd23d60781b12fcd6fc3d68db5df16994c57b78b94eed7988f5a6b482fd376dc5b084125e20a0a622e + uri-js: "npm:^4.4.1" + checksum: 14c6497b6f72843986d7344175a1aa0e2c35b1e7f7475e55bc582cddb765fca7e6bf950f465dc7846f817776d9541b706f4b5b3fbedd8dfdeb5fce6f22864264 languageName: node linkType: hard "amazon-cognito-identity-js@npm:^6.0.1": - version: 6.3.11 - resolution: "amazon-cognito-identity-js@npm:6.3.11" + version: 6.3.13 + resolution: "amazon-cognito-identity-js@npm:6.3.13" dependencies: "@aws-crypto/sha256-js": "npm:1.2.2" buffer: "npm:4.9.2" fast-base64-decode: "npm:^1.0.0" isomorphic-unfetch: "npm:^3.0.0" js-cookie: "npm:^2.2.1" - checksum: 4619e4c19770722ac243c98fb7d4aff35eb0b8f5a2db9ea31a5765f5c54deb7245e316e7e9f633f07d70520f13be157fc90c6139c5f0f2ecc59e5e7d16ee76b1 + checksum: 274785ef26573969bcc12d8f36d1f529da7fd50068ee52c7e3213c61549ce319db7c477c8c11633fc7f6bfe114fd93071228720742c0b091bafe18e7c13536a8 languageName: node linkType: hard @@ -6994,11 +6661,9 @@ __metadata: linkType: hard "ansi-escapes@npm:^6.2.0": - version: 6.2.0 - resolution: "ansi-escapes@npm:6.2.0" - dependencies: - type-fest: "npm:^3.0.0" - checksum: 3eec75deedd8b10192c5f98e4cd9715cc3ff268d33fc463c24b7d22446668bfcd4ad1803993ea89c0f51f88b5a3399572bacb7c8cb1a067fc86e189c5f3b0c7e + version: 6.2.1 + resolution: "ansi-escapes@npm:6.2.1" + checksum: a2c6f58b044be5f69662ee17073229b492daa2425a7fd99a665db6c22eab6e4ab42752807def7281c1c7acfed48f87f2362dda892f08c2c437f1b39c6b033103 languageName: node linkType: hard @@ -7261,15 +6926,16 @@ __metadata: linkType: hard "array.prototype.findlast@npm:^1.2.2": - version: 1.2.4 - resolution: "array.prototype.findlast@npm:1.2.4" + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" dependencies: - call-bind: "npm:^1.0.5" + call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.22.3" + es-abstract: "npm:^1.23.2" es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" es-shim-unscopables: "npm:^1.0.2" - checksum: 4b5145a68ebaa00ef3d61de07c6694cad73d60763079f1e7662b948e5a167b5121b0c1e6feae8df1e42ead07c21699e25242b95cd5c48e094fd530b192aa4150 + checksum: ddc952b829145ab45411b9d6adcb51a8c17c76bf89c9dd64b52d5dffa65d033da8c076ed2e17091779e83bc892b9848188d7b4b33453c5565e65a92863cb2775 languageName: node linkType: hard @@ -7286,15 +6952,17 @@ __metadata: linkType: hard "array.prototype.reduce@npm:^1.0.6": - version: 1.0.6 - resolution: "array.prototype.reduce@npm:1.0.6" + version: 1.0.7 + resolution: "array.prototype.reduce@npm:1.0.7" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" es-array-method-boxes-properly: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" is-string: "npm:^1.0.7" - checksum: 4082757ff094c372d94e5b5c7f7f12dae11cfdf41dec7cd7a54a528f6a92155442bac38eddd23a82be7e8fd9c458b124163e791cb5841372d02b1ba964a92816 + checksum: 97aac907d7b15088d5b991bad79de96f95ea0d47a701a034e2dc816e0aabaed2fb401d7fe65ab6fda05eafa58319aa2d1bac404f515e162b81b3b61a51224db2 languageName: node linkType: hard @@ -7328,15 +6996,14 @@ __metadata: languageName: node linkType: hard -"asn1.js@npm:^5.2.0": - version: 5.4.1 - resolution: "asn1.js@npm:5.4.1" +"asn1.js@npm:^4.10.1": + version: 4.10.1 + resolution: "asn1.js@npm:4.10.1" dependencies: bn.js: "npm:^4.0.0" inherits: "npm:^2.0.1" minimalistic-assert: "npm:^1.0.0" - safer-buffer: "npm:^2.1.0" - checksum: b577232fa6069cc52bb128e564002c62b2b1fe47f7137bdcd709c0b8495aa79cee0f8cc458a831b2d8675900eea0d05781b006be5e1aa4f0ae3577a73ec20324 + checksum: afa7f3ab9e31566c80175a75b182e5dba50589dcc738aa485be42bdd787e2a07246a4b034d481861123cbe646a7656f318f4f1cad2e9e5e808a210d5d6feaa88 languageName: node linkType: hard @@ -7402,7 +7069,7 @@ __metadata: languageName: node linkType: hard -"async-eventemitter@npm:^0.2.2, async-eventemitter@npm:^0.2.4": +"async-eventemitter@npm:^0.2.2": version: 0.2.4 resolution: "async-eventemitter@npm:0.2.4" dependencies: @@ -7505,7 +7172,7 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.6, available-typed-arrays@npm:^1.0.7": +"available-typed-arrays@npm:^1.0.7": version: 1.0.7 resolution: "available-typed-arrays@npm:1.0.7" dependencies: @@ -7548,13 +7215,13 @@ __metadata: linkType: hard "axios@npm:^1.4.0, axios@npm:^1.5.1": - version: 1.6.7 - resolution: "axios@npm:1.6.7" + version: 1.6.8 + resolution: "axios@npm:1.6.8" dependencies: - follow-redirects: "npm:^1.15.4" + follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 131bf8e62eee48ca4bd84e6101f211961bf6a21a33b95e5dfb3983d5a2fe50d9fffde0b57668d7ce6f65063d3dc10f2212cbcb554f75cfca99da1c73b210358d + checksum: 0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 languageName: node linkType: hard @@ -8326,7 +7993,7 @@ __metadata: languageName: node linkType: hard -"bigint-crypto-utils@npm:^3.0.23, bigint-crypto-utils@npm:^3.2.2": +"bigint-crypto-utils@npm:^3.0.23": version: 3.3.0 resolution: "bigint-crypto-utils@npm:3.3.0" checksum: 7d06fa01d63e8e9513eee629fe8a426993276b1bdca5aefd0eb3188cee7026334d29e801ef6187a5bc6105ebf26e6e79e6fab544a7da769ccf55b913e66d2a14 @@ -8348,9 +8015,9 @@ __metadata: linkType: hard "binary-extensions@npm:^2.0.0": - version: 2.2.0 - resolution: "binary-extensions@npm:2.2.0" - checksum: d73d8b897238a2d3ffa5f59c0241870043aa7471335e89ea5e1ff48edb7c2d0bb471517a3e4c5c3f4c043615caa2717b5f80a5e61e07503d51dc85cb848e665d + version: 2.3.0 + resolution: "binary-extensions@npm:2.3.0" + checksum: 75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5 languageName: node linkType: hard @@ -8651,7 +8318,7 @@ __metadata: languageName: node linkType: hard -"browserify-aes@npm:^1.0.0, browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": +"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": version: 1.2.0 resolution: "browserify-aes@npm:1.2.0" dependencies: @@ -8699,19 +8366,20 @@ __metadata: linkType: hard "browserify-sign@npm:^4.0.0": - version: 4.2.2 - resolution: "browserify-sign@npm:4.2.2" + version: 4.2.3 + resolution: "browserify-sign@npm:4.2.3" dependencies: bn.js: "npm:^5.2.1" browserify-rsa: "npm:^4.1.0" create-hash: "npm:^1.2.0" create-hmac: "npm:^1.1.7" - elliptic: "npm:^6.5.4" + elliptic: "npm:^6.5.5" + hash-base: "npm:~3.0" inherits: "npm:^2.0.4" - parse-asn1: "npm:^5.1.6" - readable-stream: "npm:^3.6.2" + parse-asn1: "npm:^5.1.7" + readable-stream: "npm:^2.3.8" safe-buffer: "npm:^5.2.1" - checksum: 4d1292e5c165d93455630515003f0e95eed9239c99e2d373920c5b56903d16296a3d23cd4bdc4d298f55ad9b83714a9e63bc4839f1166c303349a16e84e9b016 + checksum: 30c0eba3f5970a20866a4d3fbba2c5bd1928cd24f47faf995f913f1499214c6f3be14bb4d6ec1ab5c6cafb1eca9cb76ba1c2e1c04ed018370634d4e659c77216 languageName: node linkType: hard @@ -8900,8 +8568,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.2 - resolution: "cacache@npm:18.0.2" + version: 18.0.3 + resolution: "cacache@npm:18.0.3" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" @@ -8915,7 +8583,7 @@ __metadata: ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: 7992665305cc251a984f4fdbab1449d50e88c635bc43bf2785530c61d239c61b349e5734461baa461caaee65f040ab14e2d58e694f479c0810cffd181ba5eabc + checksum: dfda92840bb371fb66b88c087c61a74544363b37a265023223a99965b16a16bbb87661fe4948718d79df6e0cc04e85e62784fbcf1832b2a5e54ff4c46fbb45b7 languageName: node linkType: hard @@ -9082,9 +8750,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30000844, caniuse-lite@npm:^1.0.30001587": - version: 1.0.30001589 - resolution: "caniuse-lite@npm:1.0.30001589" - checksum: 20debfb949413f603011bc7dacaf050010778bc4f8632c86fafd1bd0c43180c95ae7c31f6c82348f6309e5e221934e327c3607a216e3f09640284acf78cd6d4d + version: 1.0.30001620 + resolution: "caniuse-lite@npm:1.0.30001620" + checksum: 3783117143fbdc98c1b91a579d0f2a7bcee7008f322ba7a2bf56a6c3d105400772c7ed8026840b4ea909ec7bf254bcc36532f2ce1b1a1240b00d0335da39b7ec languageName: node linkType: hard @@ -9139,13 +8807,13 @@ __metadata: linkType: hard "chai-as-promised@npm:^7.1.1": - version: 7.1.1 - resolution: "chai-as-promised@npm:7.1.1" + version: 7.1.2 + resolution: "chai-as-promised@npm:7.1.2" dependencies: check-error: "npm:^1.0.2" peerDependencies: - chai: ">= 2.1.2 < 5" - checksum: e25a602c3a8cd0b97ce6b0c7ddaaf4bd8517941da9f44dc65262c5268ea463f634dc495cdef6a21eaeffdb5022b6f4c3781027b8308273b7fff089c605abf6aa + chai: ">= 2.1.2 < 6" + checksum: ee20ed75296d8cbf828b2f3c9ad64627cee67b1a38b8e906ca59fe788fb6965ddb10f702ae66645ed88f15a905ade4f2d9f8540029e92e2d59b229c9f912273f languageName: node linkType: hard @@ -9501,15 +9169,15 @@ __metadata: linkType: hard "cli-table3@npm:^0.6.0, cli-table3@npm:^0.6.2": - version: 0.6.3 - resolution: "cli-table3@npm:0.6.3" + version: 0.6.5 + resolution: "cli-table3@npm:0.6.5" dependencies: "@colors/colors": "npm:1.5.0" string-width: "npm:^4.2.0" dependenciesMeta: "@colors/colors": optional: true - checksum: 39e580cb346c2eaf1bd8f4ff055ae644e902b8303c164a1b8894c0dc95941f92e001db51f49649011be987e708d9fa3183ccc2289a4d376a057769664048cc0c + checksum: d7cc9ed12212ae68241cc7a3133c52b844113b17856e11f4f81308acc3febcea7cc9fd298e70933e294dd642866b29fd5d113c2c098948701d0c35f09455de78 languageName: node linkType: hard @@ -10071,6 +9739,13 @@ __metadata: languageName: node linkType: hard +"cookie@npm:0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: f2318b31af7a31b4ddb4a678d024514df5e705f9be5909a192d7f116cfb6d45cbacf96a473fa733faa95050e7cff26e7832bb3ef94751592f1387b71c8956686 + languageName: node + linkType: hard + "cookiejar@npm:^2.1.1": version: 2.1.4 resolution: "cookiejar@npm:2.1.4" @@ -10086,9 +9761,9 @@ __metadata: linkType: hard "core-js-pure@npm:^3.0.1": - version: 3.36.0 - resolution: "core-js-pure@npm:3.36.0" - checksum: 1c5ecb37451bcebaa449e36285d27c4c79d5ff24b8bfd44491ce661cfc12b5c56471c847d306d21a56894338d00abea4993a6f8e07c71d4e887d1f71e410d22e + version: 3.37.1 + resolution: "core-js-pure@npm:3.37.1" + checksum: 38200d08862b4ef2207af72a7525f7b9ac750f5e1d84ef27a3e314aefa69518179a9b732f51ebe35c3b38606d9fa4f686fcf6eff067615cc293a3b1c84041e74 languageName: node linkType: hard @@ -10364,13 +10039,13 @@ __metadata: languageName: node linkType: hard -"d@npm:1, d@npm:^1.0.1": - version: 1.0.1 - resolution: "d@npm:1.0.1" +"d@npm:1, d@npm:^1.0.1, d@npm:^1.0.2": + version: 1.0.2 + resolution: "d@npm:1.0.2" dependencies: - es5-ext: "npm:^0.10.50" - type: "npm:^1.0.1" - checksum: 1fedcb3b956a461f64d86b94b347441beff5cef8910b6ac4ec509a2c67eeaa7093660a98b26601ac91f91260238add73bdf25867a9c0cb783774642bc4c1523f + es5-ext: "npm:^0.10.64" + type: "npm:^2.7.2" + checksum: 3e6ede10cd3b77586c47da48423b62bed161bf1a48bdbcc94d87263522e22f5dfb0e678a6dba5323fdc14c5d8612b7f7eb9e7d9e37b2e2d67a7bf9f116dabe5a languageName: node linkType: hard @@ -10390,6 +10065,39 @@ __metadata: languageName: node linkType: hard +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 8984119e59dbed906a11fcfb417d7d861936f16697a0e7216fe2c6c810f6b5e8f4a5281e73f2c28e8e9259027190ac4a33e2a65fdd7fa86ac06b76e838918583 + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: "npm:^1.0.7" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: b7d9e48a0cf5aefed9ab7d123559917b2d7e0d65531f43b2fd95b9d3a6b46042dd3fca597c42bba384e66b70d7ad66ff23932f8367b241f53d93af42cfe04ec2 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 21b0d2e53fd6e20cc4257c873bf6d36d77bd6185624b84076c0a1ddaa757b49aaf076254006341d35568e89f52eecd1ccb1a502cfb620f2beca04f48a6a62a8f + languageName: node + linkType: hard + "dataloader@npm:2.2.2, dataloader@npm:^2.2.2": version: 2.2.2 resolution: "dataloader@npm:2.2.2" @@ -10594,7 +10302,7 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1, define-data-property@npm:^1.1.2, define-data-property@npm:^1.1.4": +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1, define-data-property@npm:^1.1.4": version: 1.1.4 resolution: "define-data-property@npm:1.1.4" dependencies: @@ -10612,7 +10320,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -10748,15 +10456,15 @@ __metadata: linkType: hard "detect-port@npm:^1.3.0": - version: 1.5.1 - resolution: "detect-port@npm:1.5.1" + version: 1.6.1 + resolution: "detect-port@npm:1.6.1" dependencies: address: "npm:^1.0.1" debug: "npm:4" bin: detect: bin/detect-port.js detect-port: bin/detect-port.js - checksum: f2b204ad3a9f8e8b53fea35fcc97469f31a8e3e786a2f59fbc886397e33b5f130c5f964bf001b9a64d990047c3824f6a439308461ff19801df04ab48a754639e + checksum: 4ea9eb46a637cb21220dd0a62b6074792894fc77b2cacbc9de533d1908b2eedafa7bfd7547baaa2ac1e9c7ba7c289b34b17db896dca6da142f4fc6e2060eee17 languageName: node linkType: hard @@ -10927,14 +10635,14 @@ __metadata: linkType: hard "duplexify@npm:^4.1.1, duplexify@npm:^4.1.2": - version: 4.1.2 - resolution: "duplexify@npm:4.1.2" + version: 4.1.3 + resolution: "duplexify@npm:4.1.3" dependencies: end-of-stream: "npm:^1.4.1" inherits: "npm:^2.0.3" readable-stream: "npm:^3.1.1" - stream-shift: "npm:^1.0.0" - checksum: cacd09d8f1c58f92f83e17dffc14ece50415b32753446ed92046236a27a9e73cb914cda495d955ea12e0e615381082a511f20e219f48a06e84675c9d6950675b + stream-shift: "npm:^1.0.2" + checksum: 8a7621ae95c89f3937f982fe36d72ea997836a708471a75bb2a0eecde3330311b1e128a6dad510e0fd64ace0c56bff3484ed2e82af0e465600c82117eadfbda5 languageName: node linkType: hard @@ -10963,13 +10671,13 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.3.47, electron-to-chromium@npm:^1.4.668": - version: 1.4.681 - resolution: "electron-to-chromium@npm:1.4.681" - checksum: 5b2558dfb8bb82c20fb5fa1d9bbe06a3add47431dc3e1e4815e997be6ad387787047d9e534ed96839a9e7012520a5281c865158b09db41d10c029af003f05f94 + version: 1.4.774 + resolution: "electron-to-chromium@npm:1.4.774" + checksum: dc957ee574d14838abd16f48fb3e4bd069bf47807fe02144b850d4903265810e17abc5800a361941f787bd78692cf4f81eab70046a6757eb39e44c91ff520dd4 languageName: node linkType: hard -"elliptic@npm:6.5.4, elliptic@npm:^6.4.0, elliptic@npm:^6.5.2, elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": +"elliptic@npm:6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: @@ -10984,6 +10692,21 @@ __metadata: languageName: node linkType: hard +"elliptic@npm:^6.4.0, elliptic@npm:^6.5.2, elliptic@npm:^6.5.3, elliptic@npm:^6.5.4, elliptic@npm:^6.5.5": + version: 6.5.5 + resolution: "elliptic@npm:6.5.5" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 3e591e93783a1b66f234ebf5bd3a8a9a8e063a75073a35a671e03e3b25253b6e33ac121f7efe9b8808890fffb17b40596cc19d01e6e8d1fa13b9a56ff65597c8 + languageName: node + linkType: hard + "emoji-regex@npm:^10.3.0": version: 10.3.0 resolution: "emoji-regex@npm:10.3.0" @@ -11115,17 +10838,21 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3": - version: 1.22.4 - resolution: "es-abstract@npm:1.22.4" +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: array-buffer-byte-length: "npm:^1.0.1" arraybuffer.prototype.slice: "npm:^1.0.3" - available-typed-arrays: "npm:^1.0.6" + available-typed-arrays: "npm:^1.0.7" call-bind: "npm:^1.0.7" + data-view-buffer: "npm:^1.0.1" + data-view-byte-length: "npm:^1.0.1" + data-view-byte-offset: "npm:^1.0.0" es-define-property: "npm:^1.0.0" es-errors: "npm:^1.3.0" - es-set-tostringtag: "npm:^2.0.2" + es-object-atoms: "npm:^1.0.0" + es-set-tostringtag: "npm:^2.0.3" es-to-primitive: "npm:^1.2.1" function.prototype.name: "npm:^1.1.6" get-intrinsic: "npm:^1.2.4" @@ -11133,15 +10860,16 @@ __metadata: globalthis: "npm:^1.0.3" gopd: "npm:^1.0.1" has-property-descriptors: "npm:^1.0.2" - has-proto: "npm:^1.0.1" + has-proto: "npm:^1.0.3" has-symbols: "npm:^1.0.3" - hasown: "npm:^2.0.1" + hasown: "npm:^2.0.2" internal-slot: "npm:^1.0.7" is-array-buffer: "npm:^3.0.4" is-callable: "npm:^1.2.7" - is-negative-zero: "npm:^2.0.2" + is-data-view: "npm:^1.0.1" + is-negative-zero: "npm:^2.0.3" is-regex: "npm:^1.1.4" - is-shared-array-buffer: "npm:^1.0.2" + is-shared-array-buffer: "npm:^1.0.3" is-string: "npm:^1.0.7" is-typed-array: "npm:^1.1.13" is-weakref: "npm:^1.0.2" @@ -11149,18 +10877,18 @@ __metadata: object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.5" regexp.prototype.flags: "npm:^1.5.2" - safe-array-concat: "npm:^1.1.0" + safe-array-concat: "npm:^1.1.2" safe-regex-test: "npm:^1.0.3" - string.prototype.trim: "npm:^1.2.8" - string.prototype.trimend: "npm:^1.0.7" - string.prototype.trimstart: "npm:^1.0.7" - typed-array-buffer: "npm:^1.0.1" - typed-array-byte-length: "npm:^1.0.0" - typed-array-byte-offset: "npm:^1.0.0" - typed-array-length: "npm:^1.0.4" + string.prototype.trim: "npm:^1.2.9" + string.prototype.trimend: "npm:^1.0.8" + string.prototype.trimstart: "npm:^1.0.8" + typed-array-buffer: "npm:^1.0.2" + typed-array-byte-length: "npm:^1.0.1" + typed-array-byte-offset: "npm:^1.0.2" + typed-array-length: "npm:^1.0.6" unbox-primitive: "npm:^1.0.2" - which-typed-array: "npm:^1.1.14" - checksum: dc332c3a010c5e7b77b7ea8a4532ac455fa02e7bcabf996a47447165bafa72d0d99967407d0cf5dbbb5fbbf87f53cd8b706608ec70953523b8cd2b831b9a9d64 + which-typed-array: "npm:^1.1.15" + checksum: d27e9afafb225c6924bee9971a7f25f20c314f2d6cb93a63cada4ac11dcf42040896a6c22e5fb8f2a10767055ed4ddf400be3b1eb12297d281726de470b75666 languageName: node linkType: hard @@ -11187,7 +10915,16 @@ __metadata: languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.2": +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 1fed3d102eb27ab8d983337bb7c8b159dd2a1e63ff833ec54eea1311c96d5b08223b433060ba240541ca8adba9eee6b0a60cdbf2f80634b784febc9cc8b687b4 + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.3": version: 2.0.3 resolution: "es-set-tostringtag@npm:2.0.3" dependencies: @@ -11218,15 +10955,15 @@ __metadata: languageName: node linkType: hard -"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50, es5-ext@npm:^0.10.62, es5-ext@npm:~0.10.14": - version: 0.10.63 - resolution: "es5-ext@npm:0.10.63" +"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50, es5-ext@npm:^0.10.62, es5-ext@npm:^0.10.63, es5-ext@npm:^0.10.64, es5-ext@npm:~0.10.14": + version: 0.10.64 + resolution: "es5-ext@npm:0.10.64" dependencies: es6-iterator: "npm:^2.0.3" es6-symbol: "npm:^3.1.3" esniff: "npm:^2.0.1" next-tick: "npm:^1.1.0" - checksum: 1f20f9c73dc43cca9f1aa6908062f0a3d0bf3cee229a11a2cda6d4eca83583ceeb9b59ad36e951aa6e41ddd06d81aafac9a01de3d38a76b86f598a69ad0456bd + checksum: 4459b6ae216f3c615db086e02437bdfde851515a101577fd61b19f9b3c1ad924bab4d197981eb7f0ccb915f643f2fc10ff76b97a680e96cbb572d15a27acd9a3 languageName: node linkType: hard @@ -11249,16 +10986,16 @@ __metadata: linkType: hard "es6-symbol@npm:^3.1.1, es6-symbol@npm:^3.1.3": - version: 3.1.3 - resolution: "es6-symbol@npm:3.1.3" + version: 3.1.4 + resolution: "es6-symbol@npm:3.1.4" dependencies: - d: "npm:^1.0.1" - ext: "npm:^1.1.2" - checksum: 22982f815f00df553a89f4fb74c5048fed85df598482b4bd38dbd173174247949c72982a7d7132a58b147525398400e5f182db59b0916cb49f1e245fb0e22233 + d: "npm:^1.0.2" + ext: "npm:^1.7.0" + checksum: 777bf3388db5d7919e09a0fd175aa5b8a62385b17cb2227b7a137680cba62b4d9f6193319a102642aa23d5840d38a62e4784f19cfa5be4a2210a3f0e9b23d15d languageName: node linkType: hard -"escalade@npm:^3.1.1": +"escalade@npm:^3.1.1, escalade@npm:^3.1.2": version: 3.1.2 resolution: "escalade@npm:3.1.2" checksum: 6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 @@ -11386,55 +11123,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.52.0, eslint@npm:^8.56.0": - version: 8.56.0 - resolution: "eslint@npm:8.56.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.56.0" - "@humanwhocodes/config-array": "npm:^0.11.13" - "@humanwhocodes/module-importer": "npm:^1.0.1" - "@nodelib/fs.walk": "npm:^1.2.8" - "@ungap/structured-clone": "npm:^1.2.0" - ajv: "npm:^6.12.4" - chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" - debug: "npm:^4.3.2" - doctrine: "npm:^3.0.0" - escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.2" - eslint-visitor-keys: "npm:^3.4.3" - espree: "npm:^9.6.1" - esquery: "npm:^1.4.2" - esutils: "npm:^2.0.2" - fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" - find-up: "npm:^5.0.0" - glob-parent: "npm:^6.0.2" - globals: "npm:^13.19.0" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.0" - imurmurhash: "npm:^0.1.4" - is-glob: "npm:^4.0.0" - is-path-inside: "npm:^3.0.3" - js-yaml: "npm:^4.1.0" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" - lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.1.2" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.3" - strip-ansi: "npm:^6.0.1" - text-table: "npm:^0.2.0" - bin: - eslint: bin/eslint.js - checksum: 2be598f7da1339d045ad933ffd3d4742bee610515cd2b0d9a2b8b729395a01d4e913552fff555b559fccaefd89d7b37632825789d1b06470608737ae69ab43fb - languageName: node - linkType: hard - -"eslint@npm:^8.57.0": +"eslint@npm:^8.52.0, eslint@npm:^8.56.0, eslint@npm:^8.57.0": version: 8.57.0 resolution: "eslint@npm:8.57.0" dependencies: @@ -11745,11 +11434,11 @@ __metadata: linkType: hard "ethereum-bloom-filters@npm:^1.0.6": - version: 1.0.10 - resolution: "ethereum-bloom-filters@npm:1.0.10" + version: 1.1.0 + resolution: "ethereum-bloom-filters@npm:1.1.0" dependencies: - js-sha3: "npm:^0.8.0" - checksum: ae70b0b0b6d83beece65638a634818f0bd1d00d7a4447e17b83797f4d8db4c49491b57119c5ed081c008fb766bb8f230f3603187fd6649d58a8cf3b9aa91549c + "@noble/hashes": "npm:^1.4.0" + checksum: 54b0b7a1fdf12fe02fc8f605f213d11ea026111b9d2af79ff58e8319c904d9d6cee77c62fe70bee62c4d0c7952caf58ebaf47a889d9e4199cf4da1a361a87b53 languageName: node linkType: hard @@ -12206,8 +11895,8 @@ __metadata: linkType: hard "ethers@npm:^6.4.0": - version: 6.11.1 - resolution: "ethers@npm:6.11.1" + version: 6.12.1 + resolution: "ethers@npm:6.12.1" dependencies: "@adraffy/ens-normalize": "npm:1.10.1" "@noble/curves": "npm:1.2.0" @@ -12216,7 +11905,7 @@ __metadata: aes-js: "npm:4.0.0-beta.5" tslib: "npm:2.4.0" ws: "npm:8.5.0" - checksum: 97a920e0244ba6cd1622b58a448c87f26dad20bad242777abb2e583d045bf7752218477bd7367ba6518c2a5e2b16030afff15e87b705526d0ea667498c27ac89 + checksum: 7686e1efdb0a831578f35d69188783c225de5a6fbb1b422327bc45cee04d49a2707e73c9342a6a5eb2870ce35668c71372737439ec3993d31d83f4a0e2446cc7 languageName: node linkType: hard @@ -12463,7 +12152,7 @@ __metadata: languageName: node linkType: hard -"express@npm:4.18.2, express@npm:^4.14.0": +"express@npm:4.18.2": version: 4.18.2 resolution: "express@npm:4.18.2" dependencies: @@ -12502,16 +12191,16 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.18.1": - version: 4.18.3 - resolution: "express@npm:4.18.3" +"express@npm:^4.14.0, express@npm:^4.18.1": + version: 4.19.2 + resolution: "express@npm:4.19.2" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" body-parser: "npm:1.20.2" content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.5.0" + cookie: "npm:0.6.0" cookie-signature: "npm:1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" @@ -12537,11 +12226,11 @@ __metadata: type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 0b9eeafbac549e3c67d92d083bf1773e358359f41ad142b92121935c6348d29079b75054555b3f62de39263fffc8ba06898b09fdd3e213e28e714c03c5d9f44c + checksum: e82e2662ea9971c1407aea9fc3c16d6b963e55e3830cd0ef5e00b533feda8b770af4e3be630488ef8a752d7c75c4fcefb15892868eeaafe7353cb9e3e269fdcb languageName: node linkType: hard -"ext@npm:^1.1.2": +"ext@npm:^1.7.0": version: 1.7.0 resolution: "ext@npm:1.7.0" dependencies: @@ -12728,9 +12417,9 @@ __metadata: linkType: hard "fast-redact@npm:^3.0.0": - version: 3.3.0 - resolution: "fast-redact@npm:3.3.0" - checksum: d81562510681e9ba6404ee5d3838ff5257a44d2f80937f5024c099049ff805437d0fae0124458a7e87535cc9dcf4de305bb075cab8f08d6c720bbc3447861b4e + version: 3.5.0 + resolution: "fast-redact@npm:3.5.0" + checksum: 7e2ce4aad6e7535e0775bf12bd3e4f2e53d8051d8b630e0fa9e67f68cb0b0e6070d2f7a94b1d0522ef07e32f7c7cda5755e2b677a6538f1e9070ca053c42343a languageName: node linkType: hard @@ -13059,17 +12748,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.4": - version: 1.15.5 - resolution: "follow-redirects@npm:1.15.5" - peerDependenciesMeta: - debug: - optional: true - checksum: 418d71688ceaf109dfd6f85f747a0c75de30afe43a294caa211def77f02ef19865b547dfb73fde82b751e1cc507c06c754120b848fe5a7400b0a669766df7615 - languageName: node - linkType: hard - -"follow-redirects@npm:^1.14.9": +"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.6": version: 1.15.6 resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: @@ -13484,7 +13163,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": version: 1.2.4 resolution: "get-intrinsic@npm:1.2.4" dependencies: @@ -13704,17 +13383,17 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.3.10 - resolution: "glob@npm:10.3.10" + version: 10.3.15 + resolution: "glob@npm:10.3.15" dependencies: foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.5" + jackspeak: "npm:^2.3.6" minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" + minipass: "npm:^7.0.4" + path-scurry: "npm:^1.11.0" bin: glob: dist/esm/bin.mjs - checksum: 13d8a1feb7eac7945f8c8480e11cd4a44b24d26503d99a8d8ac8d5aefbf3e9802a2b6087318a829fad04cb4e829f25c5f4f1110c68966c498720dd261c7e344d + checksum: cda748ddc181b31b3df9548c0991800406d5cc3b3f8110e37a8751ec1e39f37cdae7d7782d5422d7df92775121cdf00599992dff22f7ff1260344843af227c2b languageName: node linkType: hard @@ -13808,11 +13487,12 @@ __metadata: linkType: hard "globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" dependencies: - define-properties: "npm:^1.1.3" - checksum: 0db6e9af102a5254630351557ac15e6909bc7459d3e3f6b001e59fe784c96d31108818f032d9095739355a88467459e6488ff16584ee6250cd8c27dec05af4b0 + define-properties: "npm:^1.2.1" + gopd: "npm:^1.0.1" + checksum: 9d156f313af79d80b1566b93e19285f481c591ad6d0d319b4be5e03750d004dde40a39a0f26f7e635f9007a3600802f53ecd85a759b86f109e80a5f705e01846 languageName: node linkType: hard @@ -13991,11 +13671,11 @@ __metadata: linkType: hard "graphql-ws@npm:^5.12.1": - version: 5.15.0 - resolution: "graphql-ws@npm:5.15.0" + version: 5.16.0 + resolution: "graphql-ws@npm:5.16.0" peerDependencies: graphql: ">=0.11 <=16" - checksum: 4fcd93ed75261681b1def8cd96d1db0fc650586b145325b3fc134ab9c27ed48fbedad3e8261e3f3df65758a332d0420b8c60e13abb1ee8329ef624e312b61ccc + checksum: 5e538c3460ca997a1634bd0f64236d8d7aa6ac75c58aba549b49953faf0dd2497f4fa43eedb0bc82cfff50426c7ce47682a670d2571fd7f3af5dcf00911c9e1b languageName: node linkType: hard @@ -14049,7 +13729,7 @@ __metadata: languageName: node linkType: hard -"handlebars@npm:^4.0.1": +"handlebars@npm:^4.0.1, handlebars@npm:^4.7.7": version: 4.7.8 resolution: "handlebars@npm:4.7.8" dependencies: @@ -14103,7 +13783,7 @@ __metadata: languageName: node linkType: hard -"hardhat-contract-sizer@npm:^2.0.1, hardhat-contract-sizer@npm:^2.0.3": +"hardhat-contract-sizer@npm:^2.0.1, hardhat-contract-sizer@npm:^2.0.3, hardhat-contract-sizer@npm:^2.10.0": version: 2.10.0 resolution: "hardhat-contract-sizer@npm:2.10.0" dependencies: @@ -14218,114 +13898,57 @@ __metadata: prompt-sync: "npm:^4.2.0" peerDependencies: "@nomiclabs/hardhat-ethers": ^2.1.1 - ethers: ^5.0.0 - hardhat: ^2.0.0 - checksum: 5cf999c706f2baa4b03898ebed5ce302ff202156b2637434748072b6250f0967e1d580c8b07b52068558adb2eba178c6aff1543877672cbd57dd34a987e46604 - languageName: node - linkType: hard - -"hardhat-storage-layout@npm:0.1.6": - version: 0.1.6 - resolution: "hardhat-storage-layout@npm:0.1.6" - dependencies: - console-table-printer: "npm:^2.9.0" - peerDependencies: - hardhat: ^2.0.3 - checksum: f88e6aaedf65281c161d4b70b94417812e3ca36d7af39d0f9bf0711d62bf0c282c41d148cad8a99964824a8a19f0eb6861666bf04244ff8f4df3c292d51fc443 - languageName: node - linkType: hard - -"hardhat-tracer@npm:^1.0.0-alpha.6": - version: 1.3.0 - resolution: "hardhat-tracer@npm:1.3.0" - dependencies: - ethers: "npm:^5.6.1" - peerDependencies: - chalk: 4.x - ethers: 5.x - hardhat: 2.x - checksum: 488d8e704cc5ddcd9d536b33d1dc8a126b129ee24c8ff3b345bfc14703b251621ab606de2587a2aef6ae9b23bdf051d83997c7adb002add357a097a9deca3ecb - languageName: node - linkType: hard - -"hardhat@npm:^2.20.1": - version: 2.21.0 - resolution: "hardhat@npm:2.21.0" - dependencies: - "@ethersproject/abi": "npm:^5.1.2" - "@metamask/eth-sig-util": "npm:^4.0.0" - "@nomicfoundation/edr": "npm:^0.2.0" - "@nomicfoundation/ethereumjs-common": "npm:4.0.4" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" - "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - "@nomicfoundation/solidity-analyzer": "npm:^0.1.0" - "@sentry/node": "npm:^5.18.1" - "@types/bn.js": "npm:^5.1.0" - "@types/lru-cache": "npm:^5.1.0" - adm-zip: "npm:^0.4.16" - aggregate-error: "npm:^3.0.0" - ansi-escapes: "npm:^4.3.0" - boxen: "npm:^5.1.2" - chalk: "npm:^2.4.2" - chokidar: "npm:^3.4.0" - ci-info: "npm:^2.0.0" - debug: "npm:^4.1.1" - enquirer: "npm:^2.3.0" - env-paths: "npm:^2.2.0" - ethereum-cryptography: "npm:^1.0.3" - ethereumjs-abi: "npm:^0.6.8" - find-up: "npm:^2.1.0" - fp-ts: "npm:1.19.3" - fs-extra: "npm:^7.0.1" - glob: "npm:7.2.0" - immutable: "npm:^4.0.0-rc.12" - io-ts: "npm:1.10.4" - keccak: "npm:^3.0.2" - lodash: "npm:^4.17.11" - mnemonist: "npm:^0.38.0" - mocha: "npm:^10.0.0" - p-map: "npm:^4.0.0" - raw-body: "npm:^2.4.1" - resolve: "npm:1.17.0" - semver: "npm:^6.3.0" - solc: "npm:0.7.3" - source-map-support: "npm:^0.5.13" - stacktrace-parser: "npm:^0.1.10" - tsort: "npm:0.0.1" - undici: "npm:^5.14.0" - uuid: "npm:^8.3.2" - ws: "npm:^7.4.6" + ethers: ^5.0.0 + hardhat: ^2.0.0 + checksum: 5cf999c706f2baa4b03898ebed5ce302ff202156b2637434748072b6250f0967e1d580c8b07b52068558adb2eba178c6aff1543877672cbd57dd34a987e46604 + languageName: node + linkType: hard + +"hardhat-storage-layout@npm:0.1.6": + version: 0.1.6 + resolution: "hardhat-storage-layout@npm:0.1.6" + dependencies: + console-table-printer: "npm:^2.9.0" peerDependencies: - ts-node: "*" - typescript: "*" - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true - bin: - hardhat: internal/cli/bootstrap.js - checksum: d7c887d147ddbd0792b5e64abfd8200c233a1815b91af908f68b167067e109f9ab6e0892d130137a745c6139bae691cee62a8e993290d4fc0a2a733e5dcce324 + hardhat: ^2.0.3 + checksum: f88e6aaedf65281c161d4b70b94417812e3ca36d7af39d0f9bf0711d62bf0c282c41d148cad8a99964824a8a19f0eb6861666bf04244ff8f4df3c292d51fc443 + languageName: node + linkType: hard + +"hardhat-storage-layout@npm:^0.1.7": + version: 0.1.7 + resolution: "hardhat-storage-layout@npm:0.1.7" + dependencies: + console-table-printer: "npm:^2.9.0" + peerDependencies: + hardhat: ^2.0.3 + checksum: 257b52a079183953d079ae221d05551391ff57adbad1ba033a3ccfa1b9df495ddd29285e67a7d03da484aa69f65850feb64a9bd7e37f53c549efd3833ed8b38c + languageName: node + linkType: hard + +"hardhat-tracer@npm:^1.0.0-alpha.6": + version: 1.3.0 + resolution: "hardhat-tracer@npm:1.3.0" + dependencies: + ethers: "npm:^5.6.1" + peerDependencies: + chalk: 4.x + ethers: 5.x + hardhat: 2.x + checksum: 488d8e704cc5ddcd9d536b33d1dc8a126b129ee24c8ff3b345bfc14703b251621ab606de2587a2aef6ae9b23bdf051d83997c7adb002add357a097a9deca3ecb languageName: node linkType: hard -"hardhat@npm:^2.6.1, hardhat@npm:^2.6.4": - version: 2.20.1 - resolution: "hardhat@npm:2.20.1" +"hardhat@npm:^2.20.1, hardhat@npm:^2.6.1, hardhat@npm:^2.6.4": + version: 2.22.4 + resolution: "hardhat@npm:2.22.4" dependencies: "@ethersproject/abi": "npm:^5.1.2" "@metamask/eth-sig-util": "npm:^4.0.0" - "@nomicfoundation/ethereumjs-block": "npm:5.0.4" - "@nomicfoundation/ethereumjs-blockchain": "npm:7.0.4" + "@nomicfoundation/edr": "npm:^0.3.7" "@nomicfoundation/ethereumjs-common": "npm:4.0.4" - "@nomicfoundation/ethereumjs-evm": "npm:2.0.4" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" - "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.4" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" "@nomicfoundation/ethereumjs-util": "npm:9.0.4" - "@nomicfoundation/ethereumjs-verkle": "npm:0.0.2" - "@nomicfoundation/ethereumjs-vm": "npm:7.0.4" "@nomicfoundation/solidity-analyzer": "npm:^0.1.0" "@sentry/node": "npm:^5.18.1" "@types/bn.js": "npm:^5.1.0" @@ -14373,7 +13996,7 @@ __metadata: optional: true bin: hardhat: internal/cli/bootstrap.js - checksum: e27f1fc6b016d7ceb62795ff47384a02ad61722cdd2ab55c91d7ff2ce31973a1ea5e462431c7033ca53e66e4722c3597664b0ebaac70104622d227e94b4fb3e0 + checksum: b9f51c40bc0d392dedb7fe866da30115a9c120b89eafe1f0afcda3cf1b379d7163e6a33a9b7a8ba78df795b477c2fd2d83ace8eb992668271b610786e320d5b7 languageName: node linkType: hard @@ -14489,7 +14112,7 @@ __metadata: languageName: node linkType: hard -"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1, has-property-descriptors@npm:^1.0.2": +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": version: 1.0.2 resolution: "has-property-descriptors@npm:1.0.2" dependencies: @@ -14512,7 +14135,7 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.1, has-tostringtag@npm:^1.0.2": +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": version: 1.0.2 resolution: "has-tostringtag@npm:1.0.2" dependencies: @@ -14578,6 +14201,16 @@ __metadata: languageName: node linkType: hard +"hash-base@npm:~3.0": + version: 3.0.4 + resolution: "hash-base@npm:3.0.4" + dependencies: + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + checksum: a13357dccb3827f0bb0b56bf928da85c428dc8670f6e4a1c7265e4f1653ce02d69030b40fd01b0f1d218a995a066eea279cded9cec72d207b593bcdfe309c2f0 + languageName: node + linkType: hard + "hash-it@npm:^6.0.0": version: 6.0.0 resolution: "hash-it@npm:6.0.0" @@ -14605,12 +14238,12 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0, hasown@npm:^2.0.1": - version: 2.0.1 - resolution: "hasown@npm:2.0.1" +"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" dependencies: function-bind: "npm:^1.1.2" - checksum: 9e27e70e8e4204f4124c8f99950d1ba2b1f5174864fd39ff26da190f9ea6488c1b3927dcc64981c26d1f637a971783c9489d62c829d393ea509e6f1ba20370bb + checksum: 3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 languageName: node linkType: hard @@ -14923,7 +14556,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.2.4": +"ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd @@ -14952,9 +14585,9 @@ __metadata: linkType: hard "immutable@npm:^4.0.0-rc.12": - version: 4.3.5 - resolution: "immutable@npm:4.3.5" - checksum: 63d2d7908241a955d18c7822fd2215b6e89ff5a1a33cc72cd475b013cbbdef7a705aa5170a51ce9f84a57f62fdddfaa34e7b5a14b33d8a43c65cc6a881d6e894 + version: 4.3.6 + resolution: "immutable@npm:4.3.6" + checksum: 7d0952a768b4fadcee47230ed86dc9505a4517095eceaf5a47e65288571c42400c6e4a2ae21eca4eda957cb7bc50720213135b62cf6a181639111f8acae128c3 languageName: node linkType: hard @@ -15418,6 +15051,15 @@ __metadata: languageName: node linkType: hard +"is-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: "npm:^1.1.13" + checksum: a3e6ec84efe303da859107aed9b970e018e2bee7ffcb48e2f8096921a493608134240e672a2072577e5f23a729846241d9634806e8a0e51d9129c56d5f65442d + languageName: node + linkType: hard + "is-date-object@npm:^1.0.1, is-date-object@npm:^1.0.5": version: 1.0.5 resolution: "is-date-object@npm:1.0.5" @@ -15635,7 +15277,7 @@ __metadata: languageName: node linkType: hard -"is-negative-zero@npm:^2.0.2": +"is-negative-zero@npm:^2.0.3": version: 2.0.3 resolution: "is-negative-zero@npm:2.0.3" checksum: bcdcf6b8b9714063ffcfa9929c575ac69bfdabb8f4574ff557dfc086df2836cf07e3906f5bbc4f2a5c12f8f3ba56af640c843cdfc74da8caed86c7c7d66fd08e @@ -15767,7 +15409,7 @@ __metadata: languageName: node linkType: hard -"is-shared-array-buffer@npm:^1.0.2": +"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.3": version: 1.0.3 resolution: "is-shared-array-buffer@npm:1.0.3" dependencies: @@ -16116,7 +15758,7 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.5": +"jackspeak@npm:^2.3.6": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" dependencies: @@ -17314,10 +16956,10 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.2.0 - resolution: "lru-cache@npm:10.2.0" - checksum: c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.2.2 + resolution: "lru-cache@npm:10.2.2" + checksum: 402d31094335851220d0b00985084288136136992979d0e015f0f1697e15d1c86052d7d53ae86b614e5b058425606efffc6969a31a091085d7a2b80a8a1e26d6 languageName: node linkType: hard @@ -17385,8 +17027,8 @@ __metadata: linkType: hard "make-fetch-happen@npm:^13.0.0": - version: 13.0.0 - resolution: "make-fetch-happen@npm:13.0.0" + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" dependencies: "@npmcli/agent": "npm:^2.0.0" cacache: "npm:^18.0.0" @@ -17397,9 +17039,10 @@ __metadata: minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" negotiator: "npm:^0.6.3" + proc-log: "npm:^4.2.0" promise-retry: "npm:^2.0.1" ssri: "npm:^10.0.0" - checksum: 43b9f6dcbc6fe8b8604cb6396957c3698857a15ba4dbc38284f7f0e61f248300585ef1eb8cc62df54e9c724af977e45b5cdfd88320ef7f53e45070ed3488da55 + checksum: df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e languageName: node linkType: hard @@ -17827,12 +17470,12 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:*, minimatch@npm:9.0.3, minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" +"minimatch@npm:*, minimatch@npm:^9.0.1, minimatch@npm:^9.0.4": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 85f407dcd38ac3e180f425e86553911d101455ca3ad5544d6a7cec16286657e4f8a9aa6695803025c55e31e35a91a2252b5dc8e7d527211278b8b65b4dbd5eac + checksum: 2c16f21f50e64922864e560ff97c587d15fd491f65d92a677a344e970fe62aafdbeafe648965fa96d33c061b4d0eabfe0213466203dd793367e7f28658cf6414 languageName: node linkType: hard @@ -17854,6 +17497,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:9.0.3": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 85f407dcd38ac3e180f425e86553911d101455ca3ad5544d6a7cec16286657e4f8a9aa6695803025c55e31e35a91a2252b5dc8e7d527211278b8b65b4dbd5eac + languageName: node + linkType: hard + "minimatch@npm:^5.0.1": version: 5.1.6 resolution: "minimatch@npm:5.1.6" @@ -17898,8 +17550,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" @@ -17908,7 +17560,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 1b63c1f3313e88eeac4689f1b71c9f086598db9a189400e3ee960c32ed89e06737fa23976c9305c2d57464fb3fcdc12749d3378805c9d6176f5569b0d0ee8a75 + checksum: 9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b languageName: node linkType: hard @@ -17965,10 +17617,10 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": - version: 7.0.4 - resolution: "minipass@npm:7.0.4" - checksum: 6c7370a6dfd257bf18222da581ba89a5eaedca10e158781232a8b5542a90547540b4b9b7e7f490e4cda43acfbd12e086f0453728ecf8c19e0ef6921bc5958ac5 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4": + version: 7.1.1 + resolution: "minipass@npm:7.1.1" + checksum: fdccc2f99c31083f45f881fd1e6971d798e333e078ab3c8988fb818c470fbd5e935388ad9adb286397eba50baebf46ef8ff487c8d3f455a69c6f3efc327bdff9 languageName: node linkType: hard @@ -18067,8 +17719,8 @@ __metadata: linkType: hard "mocha@npm:^10.0.0, mocha@npm:^10.2.0": - version: 10.3.0 - resolution: "mocha@npm:10.3.0" + version: 10.4.0 + resolution: "mocha@npm:10.4.0" dependencies: ansi-colors: "npm:4.1.1" browser-stdout: "npm:1.3.1" @@ -18093,7 +17745,7 @@ __metadata: bin: _mocha: bin/_mocha mocha: bin/mocha.js - checksum: 8dc93842468b2be5f820e5eb64208fb68ba3e5ee90cfe21a9f1d439f9ec031e8a8dc97f4d3206a376c9e05141cf689a812aedcf4545f71f69b3e9a51f312ec4a + checksum: e572e9d8c164e98f64de7e9498608de042fd841c6a7441f456a5e216e9aed2299e2c568d9dc27f2be2de06521e6b2d1dd774ab58a243b1c7697d14aec2f0f7f7 languageName: node linkType: hard @@ -18547,19 +18199,19 @@ __metadata: linkType: hard "node-gyp-build@npm:^4.2.0, node-gyp-build@npm:^4.3.0": - version: 4.8.0 - resolution: "node-gyp-build@npm:4.8.0" + version: 4.8.1 + resolution: "node-gyp-build@npm:4.8.1" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: 85324be16f81f0235cbbc42e3eceaeb1b5ab94c8d8f5236755e1435b4908338c65a4e75f66ee343cbcb44ddf9b52a428755bec16dcd983295be4458d95c8e1ad + checksum: e36ca3d2adf2b9cca316695d7687207c19ac6ed326d6d7c68d7112cebe0de4f82d6733dff139132539fcc01cf5761f6c9082a21864ab9172edf84282bc849ce7 languageName: node linkType: hard "node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" @@ -18573,7 +18225,7 @@ __metadata: which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: abddfff7d873312e4ed4a5fb75ce893a5c4fb69e7fcb1dfa71c28a6b92a7f1ef6b62790dffb39181b5a82728ba8f2f32d229cf8cbe66769fe02cea7db4a555aa + checksum: 9cc821111ca244a01fb7f054db7523ab0a0cd837f665267eb962eb87695d71fb1e681f9e21464cc2fd7c05530dc4c81b810bca1a88f7d7186909b74477491a3c languageName: node linkType: hard @@ -18610,13 +18262,13 @@ __metadata: linkType: hard "nopt@npm:^7.0.0": - version: 7.2.0 - resolution: "nopt@npm:7.2.0" + version: 7.2.1 + resolution: "nopt@npm:7.2.1" dependencies: abbrev: "npm:^2.0.0" bin: nopt: bin/nopt.js - checksum: 9bd7198df6f16eb29ff16892c77bcf7f0cc41f9fb5c26280ac0def2cf8cf319f3b821b3af83eba0e74c85807cc430a16efe0db58fe6ae1f41e69519f585b6aff + checksum: a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 languageName: node linkType: hard @@ -18675,9 +18327,9 @@ __metadata: linkType: hard "normalize-url@npm:^8.0.0": - version: 8.0.0 - resolution: "normalize-url@npm:8.0.0" - checksum: 09582d56acd562d89849d9239852c2aff225c72be726556d6883ff36de50006803d32a023c10e917bcc1c55f73f3bb16434f67992fe9b61906a3db882192753c + version: 8.0.1 + resolution: "normalize-url@npm:8.0.1" + checksum: eb439231c4b84430f187530e6fdac605c5048ef4ec556447a10c00a91fc69b52d8d8298d9d608e68d3e0f7dc2d812d3455edf425e0f215993667c3183bcab1ef languageName: node linkType: hard @@ -18779,12 +18431,12 @@ __metadata: linkType: hard "object-is@npm:^1.1.5": - version: 1.1.5 - resolution: "object-is@npm:1.1.5" + version: 1.1.6 + resolution: "object-is@npm:1.1.6" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.3" - checksum: 8c263fb03fc28f1ffb54b44b9147235c5e233dc1ca23768e7d2569740b5d860154d7cc29a30220fe28ed6d8008e2422aefdebfe987c103e1c5d190cf02d9d886 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + checksum: 506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 languageName: node linkType: hard @@ -18824,15 +18476,17 @@ __metadata: linkType: hard "object.getownpropertydescriptors@npm:^2.1.6": - version: 2.1.7 - resolution: "object.getownpropertydescriptors@npm:2.1.7" + version: 2.1.8 + resolution: "object.getownpropertydescriptors@npm:2.1.8" dependencies: array.prototype.reduce: "npm:^1.0.6" - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - safe-array-concat: "npm:^1.0.0" - checksum: 519c4eb47bd30dad1385994dbea59408c25f4bff68b29d918267091f3d597d39b04557691e94ee385fd9af7f191daffa59954e19c6f1e53215d6910d386005a2 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + gopd: "npm:^1.0.1" + safe-array-concat: "npm:^1.1.2" + checksum: 553e9562fd86637c9c169df23a56f1d810d8c9b580a6d4be11552c009f32469310c9347f3d10325abf0cd9cfe4afc521a1e903fbd24148ae7ec860e1e7c75cf3 languageName: node linkType: hard @@ -18991,16 +18645,16 @@ __metadata: linkType: hard "optionator@npm:^0.9.3": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" + version: 0.9.4 + resolution: "optionator@npm:0.9.4" dependencies: - "@aashutoshrathi/word-wrap": "npm:^1.2.3" deep-is: "npm:^0.1.3" fast-levenshtein: "npm:^2.0.6" levn: "npm:^0.4.1" prelude-ls: "npm:^1.2.1" type-check: "npm:^0.4.0" - checksum: 66fba794d425b5be51353035cf3167ce6cfa049059cbb93229b819167687e0f48d2bc4603fcb21b091c99acb516aae1083624675b15c4765b2e4693a085e959c + word-wrap: "npm:^1.2.5" + checksum: 4afb687a059ee65b61df74dfe87d8d6815cd6883cb8b3d5883a910df72d0f5d029821f37025e4bccf4048873dbdb09acc6d303d27b8f76b1a80dd5a7d5334675 languageName: node linkType: hard @@ -19264,16 +18918,17 @@ __metadata: languageName: node linkType: hard -"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.6": - version: 5.1.6 - resolution: "parse-asn1@npm:5.1.6" +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.7": + version: 5.1.7 + resolution: "parse-asn1@npm:5.1.7" dependencies: - asn1.js: "npm:^5.2.0" - browserify-aes: "npm:^1.0.0" - evp_bytestokey: "npm:^1.0.0" - pbkdf2: "npm:^3.0.3" - safe-buffer: "npm:^5.1.1" - checksum: 4ed1d9b9e120c5484d29d67bb90171aac0b73422bc016d6294160aea983275c28a27ab85d862059a36a86a97dd31b7ddd97486802ca9fac67115fe3409e9dcbd + asn1.js: "npm:^4.10.1" + browserify-aes: "npm:^1.2.0" + evp_bytestokey: "npm:^1.0.3" + hash-base: "npm:~3.0" + pbkdf2: "npm:^3.1.2" + safe-buffer: "npm:^5.2.1" + checksum: 05eb5937405c904eb5a7f3633bab1acc11f4ae3478a07ef5c6d81ce88c3c0e505ff51f9c7b935ebc1265c868343793698fc91025755a895d0276f620f95e8a82 languageName: node linkType: hard @@ -19503,13 +19158,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.11.0": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" dependencies: - lru-cache: "npm:^9.1.1 || ^10.0.0" + lru-cache: "npm:^10.2.0" minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: e5dc78a7348d25eec61ab166317e9e9c7b46818aa2c2b9006c507a6ff48c672d011292d9662527213e558f5652ce0afcc788663a061d8b59ab495681840c0c1e + checksum: 32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d languageName: node linkType: hard @@ -19552,7 +19207,7 @@ __metadata: languageName: node linkType: hard -"pbkdf2@npm:^3.0.17, pbkdf2@npm:^3.0.3, pbkdf2@npm:^3.0.9": +"pbkdf2@npm:^3.0.17, pbkdf2@npm:^3.0.3, pbkdf2@npm:^3.0.9, pbkdf2@npm:^3.1.2": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" dependencies: @@ -19589,9 +19244,9 @@ __metadata: linkType: hard "pg-connection-string@npm:^2.5.0, pg-connection-string@npm:^2.6.1, pg-connection-string@npm:^2.6.2": - version: 2.6.2 - resolution: "pg-connection-string@npm:2.6.2" - checksum: e8fdea74fcc8bdc3d7c5c6eadd9425fdba7e67fb7fe836f9c0cecad94c8984e435256657d1d8ce0483d1fedef667e7a57e32449a63cb805cb0289fc34b62da35 + version: 2.6.4 + resolution: "pg-connection-string@npm:2.6.4" + checksum: 0d0b617df0fc6507bf6a94bdcd56c7a305788a1402d69bff9773350947c8f525d6d8136128065370749a3325e99658ae40fbdcce620fb8e60126181f0591a6a6 languageName: node linkType: hard @@ -19612,18 +19267,18 @@ __metadata: linkType: hard "pg-pool@npm:^3.5.1, pg-pool@npm:^3.6.1": - version: 3.6.1 - resolution: "pg-pool@npm:3.6.1" + version: 3.6.2 + resolution: "pg-pool@npm:3.6.2" peerDependencies: pg: ">=8.0" - checksum: 47837c4e4c2b9e195cec01bd58b6e276acc915537191707ad4d6ed975fd9bc03c73f63cb7fde4cb0e08ed059e35faf60fbd03744dee3af71d4b4631ab40eeb7f + checksum: 14c524549490954b5e48457a4b808df8f619f6deeb3b395b0cd184a8f4ed65a9273fe0697ba0341a41d6745af197f1437eb1cf51fff0cbbf5b0fb3852ebe5392 languageName: node linkType: hard "pg-protocol@npm:^1.5.0, pg-protocol@npm:^1.6.0": - version: 1.6.0 - resolution: "pg-protocol@npm:1.6.0" - checksum: 318a4d1e9cebd3927b10a8bc412f5017117a1f9a5fafb628d75847da7d1ab81c33250de58596bd0990029e14e92a995a851286d60fc236692299faf509572213 + version: 1.6.1 + resolution: "pg-protocol@npm:1.6.1" + checksum: 7eadef4010ac0a3925c460be7332ca4098a5c6d5181725a62193fcfa800000ae6632d98d814f3989b42cf5fdc3b45e34c714a1959d29174e81e30730e140ae5f languageName: node linkType: hard @@ -19693,10 +19348,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: 20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400 languageName: node linkType: hard @@ -19707,10 +19362,10 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.1": - version: 4.0.1 - resolution: "picomatch@npm:4.0.1" - checksum: a036a085b18b376493e8ccef155bb03c65a2be7203582b717bb0498d1446e6a80f7f86a36e07877590abd0431f26c64c6154058c31f4f46105d3686a34fa3cf6 +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc languageName: node linkType: hard @@ -20006,6 +19661,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -20342,11 +20004,11 @@ __metadata: linkType: hard "qs@npm:^6.11.2, qs@npm:^6.4.0, qs@npm:^6.7.0, qs@npm:^6.9.4": - version: 6.11.2 - resolution: "qs@npm:6.11.2" + version: 6.12.1 + resolution: "qs@npm:6.12.1" dependencies: - side-channel: "npm:^1.0.4" - checksum: 4f95d4ff18ed480befcafa3390022817ffd3087fc65f146cceb40fc5edb9fa96cb31f648cae2fa96ca23818f0798bd63ad4ca369a0e22702fcd41379b3ab6571 + side-channel: "npm:^1.0.6" + checksum: 439e6d7c6583e7c69f2cab2c39c55b97db7ce576e4c7c469082b938b7fc8746e8d547baacb69b4cd2b6666484776c3f4840ad7163a4c5326300b0afa0acdd84b languageName: node linkType: hard @@ -20574,7 +20236,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:2 || 3, readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": +"readable-stream@npm:2 || 3, readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -20597,7 +20259,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.2, readable-stream@npm:^2.0.5, readable-stream@npm:^2.2.2, readable-stream@npm:^2.2.8, readable-stream@npm:^2.2.9, readable-stream@npm:^2.3.6, readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.2, readable-stream@npm:^2.0.5, readable-stream@npm:^2.2.2, readable-stream@npm:^2.2.8, readable-stream@npm:^2.2.9, readable-stream@npm:^2.3.6, readable-stream@npm:^2.3.8, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -21155,13 +20817,13 @@ __metadata: linkType: hard "rimraf@npm:^5.0.0": - version: 5.0.5 - resolution: "rimraf@npm:5.0.5" + version: 5.0.7 + resolution: "rimraf@npm:5.0.7" dependencies: glob: "npm:^10.3.7" bin: rimraf: dist/esm/bin.mjs - checksum: d50dbe724f33835decd88395b25ed35995077c60a50ae78ded06e0185418914e555817aad1b4243edbff2254548c2f6ad6f70cc850040bebb4da9e8cc016f586 + checksum: bd6dbfaa98ae34ce1e54d1e06045d2d63e8859d9a1979bb4a4628b652b459a2d17b17dc20ee072b034bd2d09bd691e801d24c4d9cfe94e16fdbcc8470a1d4807 languageName: node linkType: hard @@ -21222,22 +20884,6 @@ __metadata: languageName: node linkType: hard -"rust-verkle-wasm@npm:^0.0.1": - version: 0.0.1 - resolution: "rust-verkle-wasm@npm:0.0.1" - checksum: 07536a7b4d1fe37dcfc9fc19fdee630d26c9c27acd3a18da8daf21c040b87bb162098fd304e1458e4edb72d8ed4cd0e74c9fcd75edb70eb5e29a1a524916ad12 - languageName: node - linkType: hard - -"rustbn-wasm@npm:^0.2.0": - version: 0.2.0 - resolution: "rustbn-wasm@npm:0.2.0" - dependencies: - "@scure/base": "npm:^1.1.1" - checksum: 86729b25a7295f706641366a3ba2bd59a666c1ddbdc40ec4a18f8f8dd5074aaf742ffaf260e80617513954e6a247f4e06f655fe99e9d75fddbdcc4cf0bea32b7 - languageName: node - linkType: hard - "rustbn.js@npm:~0.2.0": version: 0.2.0 resolution: "rustbn.js@npm:0.2.0" @@ -21263,15 +20909,15 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.0, safe-array-concat@npm:^1.1.0": - version: 1.1.0 - resolution: "safe-array-concat@npm:1.1.0" +"safe-array-concat@npm:^1.0.0, safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" dependencies: - call-bind: "npm:^1.0.5" - get-intrinsic: "npm:^1.2.2" + call-bind: "npm:^1.0.7" + get-intrinsic: "npm:^1.2.4" has-symbols: "npm:^1.0.3" isarray: "npm:^2.0.5" - checksum: 833d3d950fc7507a60075f9bfaf41ec6dac7c50c7a9d62b1e6b071ecc162185881f92e594ff95c1a18301c881352dd6fd236d56999d5819559db7b92da9c28af + checksum: 12f9fdb01c8585e199a347eacc3bae7b5164ae805cdc8c6707199dbad5b9e30001a50a43c4ee24dc9ea32dbb7279397850e9208a7e217f4d8b1cf5d90129dec9 languageName: node linkType: hard @@ -21432,7 +21078,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.6.0, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4": +"semver@npm:7.6.0": version: 7.6.0 resolution: "semver@npm:7.6.0" dependencies: @@ -21452,6 +21098,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 97d3441e97ace8be4b1976433d1c32658f6afaff09f143e52c593bae7eef33de19e3e369c88bd985ce1042c6f441c80c6803078d1de2a9988080b66684cbb30c + languageName: node + linkType: hard + "semver@npm:~5.4.1": version: 5.4.1 resolution: "semver@npm:5.4.1" @@ -21659,16 +21314,16 @@ __metadata: linkType: hard "set-function-length@npm:^1.2.1": - version: 1.2.1 - resolution: "set-function-length@npm:1.2.1" + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" dependencies: - define-data-property: "npm:^1.1.2" + define-data-property: "npm:^1.1.4" es-errors: "npm:^1.3.0" function-bind: "npm:^1.1.2" - get-intrinsic: "npm:^1.2.3" + get-intrinsic: "npm:^1.2.4" gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.1" - checksum: 1927e296599f2c04d210c1911f1600430a5e49e04a6d8bb03dca5487b95a574da9968813a2ced9a774bd3e188d4a6208352c8f64b8d4674cdb021dca21e190ca + has-property-descriptors: "npm:^1.0.2" + checksum: 82850e62f412a258b71e123d4ed3873fa9377c216809551192bb6769329340176f109c2eeae8c22a8d386c76739855f78e8716515c818bcaef384b51110f0f3c languageName: node linkType: hard @@ -21791,15 +21446,15 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.4": - version: 1.0.5 - resolution: "side-channel@npm:1.0.5" +"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" dependencies: - call-bind: "npm:^1.0.6" + call-bind: "npm:^1.0.7" es-errors: "npm:^1.3.0" get-intrinsic: "npm:^1.2.4" object-inspect: "npm:^1.13.1" - checksum: 31312fecb68997ce2893b1f6d1fd07d6dd41e05cc938e82004f056f7de96dd9df599ef9418acdf730dda948e867e933114bd2efe4170c0146d1ed7009700c252 + checksum: d2afd163dc733cc0a39aa6f7e39bf0c436293510dbccbff446733daeaf295857dbccf94297092ec8c53e2503acac30f0b78830876f0485991d62a90e9cad305f languageName: node linkType: hard @@ -22006,24 +21661,24 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" dependencies: - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.1" debug: "npm:^4.3.4" socks: "npm:^2.7.1" - checksum: a842402fc9b8848a31367f2811ca3cd14c4106588b39a0901cd7a69029998adfc6456b0203617c18ed090542ad0c24ee4e9d4c75a0c4b75071e214227c177eb7 + checksum: 4950529affd8ccd6951575e21c1b7be8531b24d924aa4df3ee32df506af34b618c4e50d261f4cc603f1bfd8d426915b7d629966c8ce45b05fb5ad8c8b9a6459d languageName: node linkType: hard "socks@npm:^2.7.1": - version: 2.8.1 - resolution: "socks@npm:2.8.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: ac77b515c260473cc7c4452f09b20939e22510ce3ae48385c516d1d5784374d5cc75be3cb18ff66cc985a7f4f2ef8fef84e984c5ec70aad58355ed59241f40a8 + checksum: d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 languageName: node linkType: hard @@ -22127,13 +21782,29 @@ __metadata: "solhint-graph-config@workspace:^0.0.1, solhint-graph-config@workspace:packages/solhint-graph-config": version: 0.0.0-use.local resolution: "solhint-graph-config@workspace:packages/solhint-graph-config" + dependencies: + solhint-plugin-graph: "file:plugin" peerDependencies: prettier: ^3.2.5 prettier-plugin-solidity: ^1.3.1 - solhint: ^4.1.1 + solhint: ^4.5.4 languageName: unknown linkType: soft +"solhint-plugin-graph@file:node_modules/solhint-graph-config/plugin::locator=%40graphprotocol%2Fsubgraph-service%40workspace%3Apackages%2Fsubgraph-service": + version: 0.0.0 + resolution: "solhint-plugin-graph@file:node_modules/solhint-graph-config/plugin#node_modules/solhint-graph-config/plugin::hash=37bdb1&locator=%40graphprotocol%2Fsubgraph-service%40workspace%3Apackages%2Fsubgraph-service" + checksum: f77aeda80dc6f8bb93376c3b05e910874038e701793f7805e9937f0047e68d3ac8595d915a4cb12dd974c49851d2b0fdf94742b0b2865cd7bf7e3a630177dfea + languageName: node + linkType: hard + +"solhint-plugin-graph@file:plugin::locator=solhint-graph-config%40workspace%3Apackages%2Fsolhint-graph-config": + version: 0.0.0 + resolution: "solhint-plugin-graph@file:plugin#plugin::hash=37bdb1&locator=solhint-graph-config%40workspace%3Apackages%2Fsolhint-graph-config" + checksum: f77aeda80dc6f8bb93376c3b05e910874038e701793f7805e9937f0047e68d3ac8595d915a4cb12dd974c49851d2b0fdf94742b0b2865cd7bf7e3a630177dfea + languageName: node + linkType: hard + "solhint-plugin-prettier@npm:^0.1.0": version: 0.1.0 resolution: "solhint-plugin-prettier@npm:0.1.0" @@ -22147,41 +21818,9 @@ __metadata: languageName: node linkType: hard -"solhint@npm:^4.1.1": - version: 4.1.1 - resolution: "solhint@npm:4.1.1" - dependencies: - "@solidity-parser/parser": "npm:^0.16.0" - ajv: "npm:^6.12.6" - antlr4: "npm:^4.11.0" - ast-parents: "npm:^0.0.1" - chalk: "npm:^4.1.2" - commander: "npm:^10.0.0" - cosmiconfig: "npm:^8.0.0" - fast-diff: "npm:^1.2.0" - glob: "npm:^8.0.3" - ignore: "npm:^5.2.4" - js-yaml: "npm:^4.1.0" - latest-version: "npm:^7.0.0" - lodash: "npm:^4.17.21" - pluralize: "npm:^8.0.0" - prettier: "npm:^2.8.3" - semver: "npm:^7.5.2" - strip-ansi: "npm:^6.0.1" - table: "npm:^6.8.1" - text-table: "npm:^0.2.0" - dependenciesMeta: - prettier: - optional: true - bin: - solhint: solhint.js - checksum: b4bdb21bdc13f7ba3436d571a30cae6cb8dfb58ab1387df8bef25eeca25c8fbb3f625c49a5dddea41f8361aaeb4d8e2e9f986f580663ddd4574fd3d5de5f66c9 - languageName: node - linkType: hard - -"solhint@npm:^4.5.2": - version: 4.5.2 - resolution: "solhint@npm:4.5.2" +"solhint@npm:^4.1.1, solhint@npm:^4.5.2, solhint@npm:^4.5.4": + version: 4.5.4 + resolution: "solhint@npm:4.5.4" dependencies: "@solidity-parser/parser": "npm:^0.18.0" ajv: "npm:^6.12.6" @@ -22207,16 +21846,16 @@ __metadata: optional: true bin: solhint: solhint.js - checksum: a54cc8df54ed711ca6be783b9291eb9e838f518f236d4df05c6ef412ead6a21f4a5bf3bace62ca7d2ed69f4566d5289db4c8c93e0c5e23ac91401904e1f1f312 + checksum: 85bc62536c6b1269403b2af369dcfc7c63d07c6efb994f4e3c4e7e96d3511a64ab10c68635c6676e09eee289104b5d349091960994e990cacf240497170c8aed languageName: node linkType: hard -"solidity-ast@npm:^0.4.51": - version: 0.4.55 - resolution: "solidity-ast@npm:0.4.55" +"solidity-ast@npm:^0.4.38, solidity-ast@npm:^0.4.51": + version: 0.4.56 + resolution: "solidity-ast@npm:0.4.56" dependencies: array.prototype.findlast: "npm:^1.2.2" - checksum: 6f945f014a34ccc9fe8ffbbef286e9f12d52a92bee79d01f8f16e81e2ccd610bbb3e60ab4bebaea7a868382c235d0f01938e32103a68d374753c355849f2279f + checksum: 6e10e58ddae8c7a9e53551bc61b673963c6671cac12050fa77575caff1ecc6a58440af8b7d85755fdda7e02d0516e2dcd3a5a976bd91a865375274163281d160 languageName: node linkType: hard @@ -22256,8 +21895,8 @@ __metadata: linkType: hard "solidity-coverage@npm:^0.8.0": - version: 0.8.11 - resolution: "solidity-coverage@npm:0.8.11" + version: 0.8.12 + resolution: "solidity-coverage@npm:0.8.12" dependencies: "@ethersproject/abi": "npm:^5.0.9" "@solidity-parser/parser": "npm:^0.18.0" @@ -22269,7 +21908,7 @@ __metadata: global-modules: "npm:^2.0.0" globby: "npm:^10.0.1" jsonschema: "npm:^1.2.4" - lodash: "npm:^4.17.15" + lodash: "npm:^4.17.21" mocha: "npm:^10.2.0" node-emoji: "npm:^1.10.0" pify: "npm:^4.0.1" @@ -22282,7 +21921,19 @@ __metadata: hardhat: ^2.11.0 bin: solidity-coverage: plugins/bin.js - checksum: de26a3bdece5b36005fcf84b4c4e9e0affc2822d69c823d925f439876c3d5c7b1fc83d447745c6aae994ad0e5c02f4c031d4d9b2d5613184d9286116857e6437 + checksum: 500de00ca5d0ff9531bcfc54040591e90bb281714c5ad810bc6aa77bb6ab696f15a141f6bcb1a47547dca68d10e717e1705741d4cf660d7dce8700fa97e6bfaf + languageName: node + linkType: hard + +"solidity-docgen@npm:^0.6.0-beta.36": + version: 0.6.0-beta.36 + resolution: "solidity-docgen@npm:0.6.0-beta.36" + dependencies: + handlebars: "npm:^4.7.7" + solidity-ast: "npm:^0.4.38" + peerDependencies: + hardhat: ^2.8.0 + checksum: 34ca1c18b2f662e5b6e407fad9346da91807b18ca57c877d909a4e730935475b0d3a5d8e91d79113c96741f4275944f9f3176a612894f4118e16cd9a9de80c02 languageName: node linkType: hard @@ -22503,11 +22154,11 @@ __metadata: linkType: hard "ssri@npm:^10.0.0": - version: 10.0.5 - resolution: "ssri@npm:10.0.5" + version: 10.0.6 + resolution: "ssri@npm:10.0.6" dependencies: minipass: "npm:^7.0.3" - checksum: b091f2ae92474183c7ac5ed3f9811457e1df23df7a7e70c9476eaa9a0c4a0c8fc190fb45acefbf023ca9ee864dd6754237a697dc52a0fb182afe65d8e77443d8 + checksum: e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 languageName: node linkType: hard @@ -22558,7 +22209,7 @@ __metadata: languageName: node linkType: hard -"stream-shift@npm:^1.0.0": +"stream-shift@npm:^1.0.2": version: 1.0.3 resolution: "stream-shift@npm:1.0.3" checksum: 939cd1051ca750d240a0625b106a2b988c45fb5a3be0cebe9a9858cb01bc1955e8c7b9fac17a9462976bea4a7b704e317c5c2200c70f0ca715a3363b9aa4fd3b @@ -22682,36 +22333,37 @@ __metadata: languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.8, string.prototype.trim@npm:~1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" +"string.prototype.trim@npm:^1.2.9, string.prototype.trim@npm:~1.2.8": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 4f76c583908bcde9a71208ddff38f67f24c9ec8093631601666a0df8b52fad44dad2368c78895ce83eb2ae8e7068294cc96a02fc971ab234e4d5c9bb61ea4e34 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.0" + es-object-atoms: "npm:^1.0.0" + checksum: dcef1a0fb61d255778155006b372dff8cc6c4394bc39869117e4241f41a2c52899c0d263ffc7738a1f9e61488c490b05c0427faa15151efad721e1a9fb2663c2 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 53c24911c7c4d8d65f5ef5322de23a3d5b6b4db73273e05871d5ab4571ae5638f38f7f19d71d09116578fb060e5a145cc6a208af2d248c8baf7a34f44d32ce57 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 0a0b54c17c070551b38e756ae271865ac6cc5f60dabf2e7e343cceae7d9b02e1a1120a824e090e79da1b041a74464e8477e2da43e2775c85392be30a6f60963c languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 0bcf391b41ea16d4fda9c9953d0a7075171fe090d33b4cf64849af94944c50862995672ac03e0c5dba2940a213ad7f53515a668dac859ce22a0276289ae5cf4f + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: d53af1899959e53c83b64a5fd120be93e067da740e7e75acb433849aa640782fb6c7d4cd5b84c954c84413745a3764df135a8afeb22908b86a835290788d8366 languageName: node linkType: hard @@ -23002,15 +22654,15 @@ __metadata: linkType: hard "table@npm:^6.8.0, table@npm:^6.8.1": - version: 6.8.1 - resolution: "table@npm:6.8.1" + version: 6.8.2 + resolution: "table@npm:6.8.2" dependencies: ajv: "npm:^8.0.1" lodash.truncate: "npm:^4.4.2" slice-ansi: "npm:^4.0.0" string-width: "npm:^4.2.3" strip-ansi: "npm:^6.0.1" - checksum: 591ed84b2438b01c9bc02248e2238e21e8bfb73654bc5acca0d469053eb39be3db2f57d600dcf08ac983b6f50f80842c44612c03877567c2afee3aec4a033e5f + checksum: f8b348af38ee34e419d8ce7306ba00671ce6f20e861ccff22555f491ba264e8416086063ce278a8d81abfa8d23b736ec2cca7ac4029b5472f63daa4b4688b803 languageName: node linkType: hard @@ -23056,8 +22708,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -23065,7 +22717,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard @@ -23404,12 +23056,12 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.0.1": - version: 1.2.1 - resolution: "ts-api-utils@npm:1.2.1" +"ts-api-utils@npm:^1.0.1, ts-api-utils@npm:^1.3.0": + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" peerDependencies: typescript: ">=4.2.0" - checksum: 8ddb493e7ae581d3f57a2e469142feb60b420d4ad8366ab969fe8e36531f8f301f370676b47e8d97f28b5f5fd10d6f2d55f656943a8546ef95e35ce5cf117754 + checksum: f54a0ba9ed56ce66baea90a3fa087a484002e807f28a8ccb2d070c75e76bde64bd0f6dce98b3802834156306050871b67eec325cb4e918015a360a3f0868c77c languageName: node linkType: hard @@ -23690,13 +23342,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^3.0.0": - version: 3.13.1 - resolution: "type-fest@npm:3.13.1" - checksum: 547d22186f73a8c04590b70dcf63baff390078c75ea8acd366bbd510fd0646e348bd1970e47ecf795b7cff0b41d26e9c475c1fedd6ef5c45c82075fbf916b629 - languageName: node - linkType: hard - "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -23707,13 +23352,6 @@ __metadata: languageName: node linkType: hard -"type@npm:^1.0.1": - version: 1.2.0 - resolution: "type@npm:1.2.0" - checksum: 444660849aaebef8cbb9bc43b28ec2068952064cfce6a646f88db97aaa2e2d6570c5629cd79238b71ba23aa3f75146a0b96e24e198210ee0089715a6f8889bf7 - languageName: node - linkType: hard - "type@npm:^2.7.2": version: 2.7.2 resolution: "type@npm:2.7.2" @@ -23804,7 +23442,7 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.1": +"typed-array-buffer@npm:^1.0.2": version: 1.0.2 resolution: "typed-array-buffer@npm:1.0.2" dependencies: @@ -23815,7 +23453,7 @@ __metadata: languageName: node linkType: hard -"typed-array-byte-length@npm:^1.0.0": +"typed-array-byte-length@npm:^1.0.1": version: 1.0.1 resolution: "typed-array-byte-length@npm:1.0.1" dependencies: @@ -23828,7 +23466,7 @@ __metadata: languageName: node linkType: hard -"typed-array-byte-offset@npm:^1.0.0": +"typed-array-byte-offset@npm:^1.0.2": version: 1.0.2 resolution: "typed-array-byte-offset@npm:1.0.2" dependencies: @@ -23842,9 +23480,9 @@ __metadata: languageName: node linkType: hard -"typed-array-length@npm:^1.0.4": - version: 1.0.5 - resolution: "typed-array-length@npm:1.0.5" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" @@ -23852,7 +23490,7 @@ __metadata: has-proto: "npm:^1.0.3" is-typed-array: "npm:^1.1.13" possible-typed-array-names: "npm:^1.0.0" - checksum: 5cc0f79196e70a92f8f40846cfa62b3de6be51e83f73655e137116cf65e3c29a288502b18cc8faf33c943c2470a4569009e1d6da338441649a2db2f135761ad5 + checksum: 74253d7dc488eb28b6b2711cf31f5a9dcefc9c41b0681fd1c178ed0a1681b4468581a3626d39cd4df7aee3d3927ab62be06aa9ca74e5baf81827f61641445b77 languageName: node linkType: hard @@ -23873,17 +23511,18 @@ __metadata: linkType: hard "typescript-eslint@npm:^7.0.2": - version: 7.0.2 - resolution: "typescript-eslint@npm:7.0.2" + version: 7.9.0 + resolution: "typescript-eslint@npm:7.9.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:7.0.2" - "@typescript-eslint/parser": "npm:7.0.2" + "@typescript-eslint/eslint-plugin": "npm:7.9.0" + "@typescript-eslint/parser": "npm:7.9.0" + "@typescript-eslint/utils": "npm:7.9.0" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 947216bccdb392c1e5f1228772185afbe306db305f1f61343d3cb315aa6c80a928709172498af62536b50c1e7c91e263eed7886bb4b328ca8850ffb1ea71a3d9 + checksum: dacdd8b278d519eea1d980c71dd301a0b68fe1100aa8eaa9e3b80acd7089765ef50bdf369b7c11ddc5f4be6ac6d90cc9283db549003c3df8cfabbe4f44a36b53 languageName: node linkType: hard @@ -23897,23 +23536,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.0.4, typescript@npm:^5.1.6, typescript@npm:^5.3.3": - version: 5.3.3 - resolution: "typescript@npm:5.3.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: e33cef99d82573624fc0f854a2980322714986bc35b9cb4d1ce736ed182aeab78e2cb32b385efa493b2a976ef52c53e20d6c6918312353a91850e2b76f1ea44f - languageName: node - linkType: hard - -"typescript@npm:^5.2.2": - version: 5.4.2 - resolution: "typescript@npm:5.4.2" +"typescript@npm:^5.0.4, typescript@npm:^5.1.6, typescript@npm:^5.2.2, typescript@npm:^5.3.3": + version: 5.4.5 + resolution: "typescript@npm:5.4.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 583ff68cafb0c076695f72d61df6feee71689568179fb0d3a4834dac343df6b6ed7cf7b6f6c801fa52d43cd1d324e2f2d8ae4497b09f9e6cfe3d80a6d6c9ca52 + checksum: 2954022ada340fd3d6a9e2b8e534f65d57c92d5f3989a263754a78aba549f7e6529acc1921913560a4b816c46dce7df4a4d29f9f11a3dc0d4213bb76d043251e languageName: node linkType: hard @@ -23927,23 +23556,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin, typescript@patch:typescript@npm%3A^5.1.6#optional!builtin, typescript@patch:typescript@npm%3A^5.3.3#optional!builtin": - version: 5.3.3 - resolution: "typescript@patch:typescript@npm%3A5.3.3#optional!builtin::version=5.3.3&hash=e012d7" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 1d0a5f4ce496c42caa9a30e659c467c5686eae15d54b027ee7866744952547f1be1262f2d40de911618c242b510029d51d43ff605dba8fb740ec85ca2d3f9500 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.2.2#optional!builtin": - version: 5.4.2 - resolution: "typescript@patch:typescript@npm%3A5.4.2#optional!builtin::version=5.4.2&hash=e012d7" +"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin, typescript@patch:typescript@npm%3A^5.1.6#optional!builtin, typescript@patch:typescript@npm%3A^5.2.2#optional!builtin, typescript@patch:typescript@npm%3A^5.3.3#optional!builtin": + version: 5.4.5 + resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=e012d7" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 22e2f213c3ffe5960c5eaec6c95c04e01858fed57a94be250746f540b935b2c18c3c3fc80d3ab65d28c0aba1eb76284557ba3bf521d28caee811c44ba2b648f9 + checksum: 9cf4c053893bcf327d101b6c024a55baf05430dc30263f9adb1bf354aeffc11306fe1f23ba2f9a0209674359f16219b5b7d229e923477b94831d07d5a33a4217 languageName: node linkType: hard @@ -24083,11 +23702,11 @@ __metadata: linkType: hard "undici@npm:^5.14.0": - version: 5.28.3 - resolution: "undici@npm:5.28.3" + version: 5.28.4 + resolution: "undici@npm:5.28.4" dependencies: "@fastify/busboy": "npm:^2.0.0" - checksum: 3c559ae50ef3104b7085251445dda6f4de871553b9e290845649d2f80b06c0c9cfcdf741b0029c6b20d36c82e6a74dc815b139fa9a26757d70728074ca6d6f5c + checksum: 08d0f2596553aa0a54ca6e8e9c7f45aef7d042c60918564e3a142d449eda165a80196f6ef19ea2ef2e6446959e293095d8e40af1236f0d67223b06afac5ecad7 languageName: node linkType: hard @@ -24176,16 +23795,16 @@ __metadata: linkType: hard "update-browserslist-db@npm:^1.0.13": - version: 1.0.13 - resolution: "update-browserslist-db@npm:1.0.13" + version: 1.0.16 + resolution: "update-browserslist-db@npm:1.0.16" dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" + escalade: "npm:^3.1.2" + picocolors: "npm:^1.0.1" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 + checksum: 5995399fc202adbb51567e4810e146cdf7af630a92cc969365a099150cb00597e425cc14987ca7080b09a4d0cfd2a3de53fbe72eebff171aed7f9bb81f9bf405 languageName: node linkType: hard @@ -24207,7 +23826,7 @@ __metadata: languageName: node linkType: hard -"uri-js@npm:^4.2.2": +"uri-js@npm:^4.2.2, uri-js@npm:^4.4.1": version: 4.4.1 resolution: "uri-js@npm:4.4.1" dependencies: @@ -24383,9 +24002,9 @@ __metadata: linkType: hard "validator@npm:^13.7.0, validator@npm:^13.9.0": - version: 13.11.0 - resolution: "validator@npm:13.11.0" - checksum: 0107da3add5a4ebc6391dac103c55f6d8ed055bbcc29a4c9cbf89eacfc39ba102a5618c470bdc33c6487d30847771a892134a8c791f06ef0962dd4b7a60ae0f5 + version: 13.12.0 + resolution: "validator@npm:13.12.0" + checksum: 21d48a7947c9e8498790550f56cd7971e0e3d724c73388226b109c1bac2728f4f88caddfc2f7ed4b076f9b0d004316263ac786a17e9c4edf075741200718cd32 languageName: node linkType: hard @@ -25323,16 +24942,16 @@ __metadata: languageName: node linkType: hard -"webcrypto-core@npm:^1.7.8": - version: 1.7.8 - resolution: "webcrypto-core@npm:1.7.8" +"webcrypto-core@npm:^1.7.9": + version: 1.7.9 + resolution: "webcrypto-core@npm:1.7.9" dependencies: "@peculiar/asn1-schema": "npm:^2.3.8" "@peculiar/json-schema": "npm:^1.1.12" asn1js: "npm:^3.0.1" pvtsutils: "npm:^1.3.5" tslib: "npm:^2.6.2" - checksum: 4c6ef9ae4ae27489f88b7c571494b058120178528f25efe87b97cbc64ead03a6468a614f6269927d13735e4f5ce1d1f7599cf4385ee9b61a13921964a5748a66 + checksum: 29075c0fd6afdd11473dcf98623b929fae6a0861a54725af109df824e3c55c00580103a2f934baabff52d588e9c6c3892db80346061fd835c55e0a83264c19f5 languageName: node linkType: hard @@ -25358,16 +24977,16 @@ __metadata: linkType: hard "websocket@npm:^1.0.31, websocket@npm:^1.0.32": - version: 1.0.34 - resolution: "websocket@npm:1.0.34" + version: 1.0.35 + resolution: "websocket@npm:1.0.35" dependencies: bufferutil: "npm:^4.0.1" debug: "npm:^2.2.0" - es5-ext: "npm:^0.10.50" + es5-ext: "npm:^0.10.63" typedarray-to-buffer: "npm:^3.1.5" utf-8-validate: "npm:^5.0.2" yaeti: "npm:^0.0.6" - checksum: a7e17d24edec685fdf055940ff9c6a15e726df5bb5e537382390bd1ab978fc8c0d71cd2842bb628e361d823aafd43934cc56aa5b979d08e52461be7da8d01eee + checksum: 8be9a68dc0228f18058c9010d1308479f05050af8f6d68b9dbc6baebd9ab484c15a24b2521a5d742a9d78e62ee19194c532992f1047a9b9adf8c3eedb0b1fcdc languageName: node linkType: hard @@ -25432,16 +25051,16 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.2": - version: 1.1.14 - resolution: "which-typed-array@npm:1.1.14" +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" dependencies: - available-typed-arrays: "npm:^1.0.6" - call-bind: "npm:^1.0.5" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" gopd: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.1" - checksum: 0960f1e77807058819451b98c51d4cd72031593e8de990b24bd3fc22e176f5eee22921d68d852297c786aec117689f0423ed20aa4fde7ce2704d680677891f56 + has-tostringtag: "npm:^1.0.2" + checksum: 4465d5348c044032032251be54d8988270e69c6b7154f8fcb2a47ff706fe36f7624b3a24246b8d9089435a8f4ec48c1c1025c5d6b499456b9e5eff4f48212983 languageName: node linkType: hard @@ -25496,7 +25115,7 @@ __metadata: languageName: node linkType: hard -"winston-transport@npm:^4.5.0": +"winston-transport@npm:^4.7.0": version: 4.7.0 resolution: "winston-transport@npm:4.7.0" dependencies: @@ -25508,8 +25127,8 @@ __metadata: linkType: hard "winston@npm:*, winston@npm:^3.3.3": - version: 3.11.0 - resolution: "winston@npm:3.11.0" + version: 3.13.0 + resolution: "winston@npm:3.13.0" dependencies: "@colors/colors": "npm:^1.6.0" "@dabh/diagnostics": "npm:^2.0.2" @@ -25521,8 +25140,8 @@ __metadata: safe-stable-stringify: "npm:^2.3.1" stack-trace: "npm:0.0.x" triple-beam: "npm:^1.3.0" - winston-transport: "npm:^4.5.0" - checksum: 7e1f8919cbdc62cfe46e6204d79a83e1364696ef61111483f3ecf204988922383fe74192c5bc9f89df9b47caf24c2d34f5420ef6f3b693f8d1286b46432e97be + winston-transport: "npm:^4.7.0" + checksum: 2c3cc7389a691e1638edcb0d4bfea72caa82d87d5681ec6131ac9bae780d94d06fb7b112edcd4ec37c8b947a1b64943941b761e34d67c6b0dac6e9c31ae4b25b languageName: node linkType: hard @@ -25549,7 +25168,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:~1.2.3": +"word-wrap@npm:^1.2.5, word-wrap@npm:~1.2.3": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" checksum: e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20 @@ -25722,8 +25341,8 @@ __metadata: linkType: hard "ws@npm:^8.12.0, ws@npm:^8.13.0": - version: 8.16.0 - resolution: "ws@npm:8.16.0" + version: 8.17.0 + resolution: "ws@npm:8.17.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -25732,7 +25351,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: a7783bb421c648b1e622b423409cb2a58ac5839521d2f689e84bc9dc41d59379c692dd405b15a997ea1d4c0c2e5314ad707332d0c558f15232d2bc07c0b4618a + checksum: 55241ec93a66fdfc4bf4f8bc66c8eb038fda2c7a4ee8f6f157f2ca7dc7aa76aea0c0da0bf3adb2af390074a70a0e45456a2eaf80e581e630b75df10a64b0a990 languageName: node linkType: hard @@ -26044,17 +25663,17 @@ __metadata: linkType: hard "zod-to-json-schema@npm:^3.20.5": - version: 3.22.4 - resolution: "zod-to-json-schema@npm:3.22.4" + version: 3.23.0 + resolution: "zod-to-json-schema@npm:3.23.0" peerDependencies: - zod: ^3.22.4 - checksum: a949720c165347982a4abf5d612b78bebc2b5fb1217d22e20c024782ce6a9ae0baffe5deb6ba6f961ffa7b28b888c37f744bbfee6d7e9d74f2ec1f94d6968f0d + zod: ^3.23.3 + checksum: bcd966fa040765d7170a89c0c5f1717575e7d8823b84cbbb606689d494ae308c9eaadd4b71a74752e3170deef64c1f1bb2985f4663c44a0ed2e7854ff6fda724 languageName: node linkType: hard "zod@npm:^3.21.4": - version: 3.22.4 - resolution: "zod@npm:3.22.4" - checksum: 7578ab283dac0eee66a0ad0fc4a7f28c43e6745aadb3a529f59a4b851aa10872b3890398b3160f257f4b6817b4ce643debdda4fb21a2c040adda7862cab0a587 + version: 3.23.8 + resolution: "zod@npm:3.23.8" + checksum: 8f14c87d6b1b53c944c25ce7a28616896319d95bc46a9660fe441adc0ed0a81253b02b5abdaeffedbeb23bdd25a0bf1c29d2c12dd919aef6447652dd295e3e69 languageName: node linkType: hard From 16eabd820382321e180309bc56d7f781159a663c Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 17 May 2024 22:55:47 -0300 Subject: [PATCH 021/277] fix: merge conflicts errors --- .../contracts/staking/IHorizonStaking.sol | 152 ------------------ .../contracts/HorizonStakingExtension.sol | 3 +- .../contracts/payments/GraphPayments.sol | 2 +- 3 files changed, 3 insertions(+), 154 deletions(-) delete mode 100644 packages/contracts/contracts/staking/IHorizonStaking.sol diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol deleted file mode 100644 index d55520db5..000000000 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.7.6 <0.9.0; -pragma abicoder v2; - -interface Test { - function test() external returns (uint256); -} - -interface IHorizonStaking { - struct Provision { - // Service provider that created the provision - address serviceProvider; - // tokens in the provision - uint256 tokens; - // tokens that are being thawed (and will stop being slashable soon) - uint256 tokensThawing; - // timestamp of provision creation - uint64 createdAt; - // authority to slash the provision - address verifier; - // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed - uint32 maxVerifierCut; - // time, in seconds, tokens must thaw before being withdrawn - uint64 thawingPeriod; - } - - // the new "Indexer" struct - struct ServiceProviderInternal { - // Tokens on the Service Provider stake (staked by the provider) - uint256 tokensStaked; - // Tokens used in allocations - uint256 __DEPRECATED_tokensAllocated; - // Tokens locked for withdrawal subject to thawing period - uint256 __DEPRECATED_tokensLocked; - // Block when locked tokens can be withdrawn - uint256 __DEPRECATED_tokensLockedUntil; - // tokens used in a provision - uint256 tokensProvisioned; - // tokens that initiated a thawing in any one of the provider's provisions - uint256 tokensRequestedThaw; - // tokens that have been removed from any one of the provider's provisions after thawing - uint256 tokensFulfilledThaw; - // provisions that take priority for undelegation force thawing - bytes32[] forceThawProvisions; - } - - struct ServiceProvider { - // Tokens on the provider stake (staked by the provider) - uint256 tokensStaked; - // tokens used in a provision - uint256 tokensProvisioned; - // tokens that initiated a thawing in any one of the provider's provisions - uint256 tokensRequestedThaw; - // tokens that have been removed from any one of the provider's provisions after thawing - uint256 tokensFulfilledThaw; - // provisions that take priority for undelegation force thawing - bytes32[] forceThawProvisions; - } - - struct DelegationPool { - uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase - uint32 __DEPRECATED_indexingRewardCut; // in PPM - uint32 __DEPRECATED_queryFeeCut; // in PPM - uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated - uint256 tokens; // Total tokens as pool reserves - uint256 shares; // Total shares minted in the pool - mapping(address => Delegation) delegators; // Mapping of delegator => Delegation - } - - struct Delegation { - // shares owned by the delegator in the pool - uint256 shares; - // tokens delegated to the pool - uint256 tokens; - // Timestamp when locked tokens can be undelegated (after the timelock) - uint256 tokensLockedUntil; - } - - struct ThawRequest { - // tokens that are being thawed by this request - uint256 tokens; - // the provision id to which this request corresponds to - bytes32 provisionId; - // the address that initiated the thaw request, allowed to remove the funds once thawed - address owner; - // the timestamp when the thawed funds can be removed from the provision - uint64 thawingUntil; - // the value of `ServiceProvider.tokensRequestedThaw` the moment the thaw request is created - uint256 tokensRequestedThawSnapshot; - } - - // whitelist/deny a verifier - function allowVerifier(address verifier, bool allow) external; - - // deposit stake - function stake(uint256 tokens) external; - - // create a provision - function provision(uint256 tokens, address verifier, uint256 maxVerifierCut, uint256 thawingPeriod) external; - - // initiate a thawing to remove tokens from a provision - function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId); - - // moves thawed stake from a provision back into the provider's available stake - function deprovision(bytes32 thawRequestId) external; - - // moves thawed stake from one provision into another provision - function reprovision(bytes32 thawRequestId, bytes32 provisionId) external; - - // moves thawed stake back to the owner's account - stake is removed from the protocol - function withdraw(bytes32 thawRequestId) external; - - // delegate tokens to a provider - function delegate(address serviceProvider, uint256 tokens) external; - - // undelegate tokens - function undelegate( - address serviceProvider, - uint256 tokens, - bytes32[] calldata provisions - ) external returns (bytes32 thawRequestId); - - // slash a service provider - function slash(bytes32 provisionId, uint256 tokens, uint256 verifierAmount) external; - - // set the Service Provider's preferred provisions to be force thawed - function setForceThawProvisions(bytes32[] calldata provisions) external; - - // total staked tokens to the provider - // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` - function getStake(address serviceProvider) external view returns (uint256 tokens); - - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) external view returns (uint256 tokens); - - // staked tokens the provider can provision before hitting the delegation cap - // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` - function getCapacity(address serviceProvider) external view returns (uint256 tokens); - - // provisioned tokens that are not being used - // `Provision.tokens - Provision.tokensThawing` - function getTokensAvailable(bytes32 provision) external view returns (uint256 tokens); - - function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); - - function getProvision(bytes32 provision) external view returns (Provision memory); - - function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256 delegationCut); - function addToDelegationPool(address serviceProvider, uint256 tokens) external; -} diff --git a/packages/horizon/contracts/HorizonStakingExtension.sol b/packages/horizon/contracts/HorizonStakingExtension.sol index 890e34cd8..1ec8b2c45 100644 --- a/packages/horizon/contracts/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/HorizonStakingExtension.sol @@ -8,7 +8,8 @@ import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/I import { IHorizonStakingExtension } from "./IHorizonStakingExtension.sol"; import { MathUtils } from "./utils/MathUtils.sol"; -act +/** + * @title L2Staking contract * @dev 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. diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index f47ac1414..652183fd3 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -8,7 +8,7 @@ import { GraphDirectory } from "../GraphDirectory.sol"; import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; import { TokenUtils } from "../utils/TokenUtils.sol"; -aphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { +contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { // -- Errors -- error GraphPaymentsNotThawing(); From 06d8308ebf2a1e913c5e8a4b05e27fdcf813dcd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 20 May 2024 11:52:26 -0300 Subject: [PATCH 022/277] chore: turn solhint plugin into package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- README.md | 3 +- package.json | 1 + packages/solhint-graph-config/package.json | 3 +- .../plugin => solhint-plugin-graph}/index.js | 0 .../package.json | 4 +- packages/subgraph-service/package.json | 2 +- yarn.lock | 50 ++++++++----------- 7 files changed, 29 insertions(+), 34 deletions(-) rename packages/{solhint-graph-config/plugin => solhint-plugin-graph}/index.js (100%) rename packages/{solhint-graph-config/plugin => solhint-plugin-graph}/package.json (69%) diff --git a/README.md b/README.md index d9b46bb52..eb1b61d06 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,8 @@ This repository is a Yarn workspaces monorepo containing the following packages: | [eslint-graph-config](./packages/eslint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for TypeScript projects. | | [horizon](./packages/horizon) | [![npm version]()]() | Contracts for Graph Horizon, the next iteration of The Graph protocol. | | [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 | -| [solhint-graph-config](./packages/eslint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for Solidity projects. | +| [solhint-graph-config](./packages/solhint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for Solidity projects. | +| [solhint-plugin-graph](./packages/solhint-plugin-graph) | [![npm version]()]() | Plugin for Solhint with specific Graph linting rules. | | [subgraph-service](./packages/subgraph-service) | [![npm version]()]() | Contracts for the Subgraph data service in Graph Horizon. | | [token-distribution](./packages/token-distribution) | - | Contracts managing token locks for network participants | diff --git a/package.json b/package.json index 126006c96..6b82fd5a4 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "packages/horizon", "packages/sdk", "packages/solhint-graph-config", + "packages/solhint-plugin-graph", "packages/subgraph-service", "packages/token-distribution" ], diff --git a/packages/solhint-graph-config/package.json b/packages/solhint-graph-config/package.json index d976b3cb9..5b516ed58 100644 --- a/packages/solhint-graph-config/package.json +++ b/packages/solhint-graph-config/package.json @@ -1,12 +1,13 @@ { "name": "solhint-graph-config", + "private": true, "version": "0.0.1", "description": "Linting and formatting rules for The Graph's Solidity projects", "main": "index.js", "author": "The Graph Team", "license": "GPL-2.0-or-later", "dependencies": { - "solhint-plugin-graph": "file:plugin" + "solhint-plugin-graph": "workspace:*" }, "peerDependencies": { "prettier": "^3.2.5", diff --git a/packages/solhint-graph-config/plugin/index.js b/packages/solhint-plugin-graph/index.js similarity index 100% rename from packages/solhint-graph-config/plugin/index.js rename to packages/solhint-plugin-graph/index.js diff --git a/packages/solhint-graph-config/plugin/package.json b/packages/solhint-plugin-graph/package.json similarity index 69% rename from packages/solhint-graph-config/plugin/package.json rename to packages/solhint-plugin-graph/package.json index 53bab497d..1b1c0f568 100644 --- a/packages/solhint-graph-config/plugin/package.json +++ b/packages/solhint-plugin-graph/package.json @@ -1,5 +1,5 @@ { "name": "solhint-plugin-graph", - "version": "0.0.0", + "version": "0.0.1", "private": true -} \ No newline at end of file +} diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index f66d229de..144263417 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -39,7 +39,7 @@ "prettier-plugin-solidity": "^1.3.1", "solhint": "^4.5.4", "solhint-graph-config": "workspace:^0.0.1", - "solhint-plugin-graph": "file:node_modules/solhint-graph-config/plugin", + "solhint-plugin-graph": "workspace:^0.0.1", "solidity-coverage": "^0.8.0", "solidity-docgen": "^0.6.0-beta.36", "ts-node": ">=8.0.0", diff --git a/yarn.lock b/yarn.lock index 1e14c7d52..bed525f83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -863,8 +863,8 @@ __metadata: linkType: hard "@changesets/cli@npm:^2.27.1": - version: 2.27.2 - resolution: "@changesets/cli@npm:2.27.2" + version: 2.27.3 + resolution: "@changesets/cli@npm:2.27.3" dependencies: "@babel/runtime": "npm:^7.20.1" "@changesets/apply-release-plan": "npm:^7.0.1" @@ -900,7 +900,7 @@ __metadata: tty-table: "npm:^4.1.5" bin: changeset: bin.js - checksum: c2fd356b235bb27de0267389af38bca356d1c61892d0d3e114cec2e628aa6e7aadfe1828d9024b9c7d8005c3b968760ab4d781d4ce3a04309d5263d710341bec + checksum: fee10ae204926dbf4847111bf49ca93dc5b43a55b48635e2e08e71ab8442cf414c8165ae11174d6366ef12305274ea1b75beb14ca74b9a766d82b8c32148199b languageName: node linkType: hard @@ -3024,7 +3024,7 @@ __metadata: prettier-plugin-solidity: "npm:^1.3.1" solhint: "npm:^4.5.4" solhint-graph-config: "workspace:^0.0.1" - solhint-plugin-graph: "file:node_modules/solhint-graph-config/plugin" + solhint-plugin-graph: "workspace:^0.0.1" solidity-coverage: "npm:^0.8.0" solidity-docgen: "npm:^0.6.0-beta.36" ts-node: "npm:>=8.0.0" @@ -4766,28 +4766,28 @@ __metadata: linkType: hard "@openzeppelin/defender-admin-client@npm:^1.46.0": - version: 1.54.2 - resolution: "@openzeppelin/defender-admin-client@npm:1.54.2" + version: 1.54.4 + resolution: "@openzeppelin/defender-admin-client@npm:1.54.4" dependencies: - "@openzeppelin/defender-base-client": "npm:1.54.2" + "@openzeppelin/defender-base-client": "npm:1.54.4" axios: "npm:^1.4.0" ethers: "npm:^5.7.2" lodash: "npm:^4.17.19" node-fetch: "npm:^2.6.0" - checksum: fff2a74f840168d65a7cc51992610c199eb0d2b54b63f84060dded898d2730e0b008b3f492251ec99a697d45e69987a203ee005b5912e51a2786407755e3e53f + checksum: a44439ebde420aa35b36db7c2845978dd099e0fb6edc394e7b65be67ec1135e99ccc8059e78cb70c8a8fd5598ba40d082648664af95f9cb97a7673c075f64abb languageName: node linkType: hard -"@openzeppelin/defender-base-client@npm:1.54.2, @openzeppelin/defender-base-client@npm:^1.46.0": - version: 1.54.2 - resolution: "@openzeppelin/defender-base-client@npm:1.54.2" +"@openzeppelin/defender-base-client@npm:1.54.4, @openzeppelin/defender-base-client@npm:^1.46.0": + version: 1.54.4 + resolution: "@openzeppelin/defender-base-client@npm:1.54.4" dependencies: amazon-cognito-identity-js: "npm:^6.0.1" async-retry: "npm:^1.3.3" axios: "npm:^1.4.0" lodash: "npm:^4.17.19" node-fetch: "npm:^2.6.0" - checksum: b30c5c5ed47ed0ff788025abd0cdfc816fdbd49065c221be7e760385e5cbf5b05488ed1cfb040c5cbe0a1ca6cc6af035dc88a6e5b2c09fb9ae4ae048493014bd + checksum: 636614a8012cfbbe065b8ccc3ef6a16635e2f1b48f7421242de81f74def99a51795464e9a2bd02e7305ff32b339a8847d7733452e6fe7810d4badd0c2086c38f languageName: node linkType: hard @@ -7215,13 +7215,13 @@ __metadata: linkType: hard "axios@npm:^1.4.0, axios@npm:^1.5.1": - version: 1.6.8 - resolution: "axios@npm:1.6.8" + version: 1.7.1 + resolution: "axios@npm:1.7.1" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 + checksum: 554395472f18f4ddb43b4be2900473bc1a4d589464a8ab16f6954c53d9cace4317d5c9e009d5bb05f098d9565b2fa45f152a5d4cecb87536c8f0c370c25a7770 languageName: node linkType: hard @@ -21783,7 +21783,7 @@ __metadata: version: 0.0.0-use.local resolution: "solhint-graph-config@workspace:packages/solhint-graph-config" dependencies: - solhint-plugin-graph: "file:plugin" + solhint-plugin-graph: "workspace:*" peerDependencies: prettier: ^3.2.5 prettier-plugin-solidity: ^1.3.1 @@ -21791,19 +21791,11 @@ __metadata: languageName: unknown linkType: soft -"solhint-plugin-graph@file:node_modules/solhint-graph-config/plugin::locator=%40graphprotocol%2Fsubgraph-service%40workspace%3Apackages%2Fsubgraph-service": - version: 0.0.0 - resolution: "solhint-plugin-graph@file:node_modules/solhint-graph-config/plugin#node_modules/solhint-graph-config/plugin::hash=37bdb1&locator=%40graphprotocol%2Fsubgraph-service%40workspace%3Apackages%2Fsubgraph-service" - checksum: f77aeda80dc6f8bb93376c3b05e910874038e701793f7805e9937f0047e68d3ac8595d915a4cb12dd974c49851d2b0fdf94742b0b2865cd7bf7e3a630177dfea - languageName: node - linkType: hard - -"solhint-plugin-graph@file:plugin::locator=solhint-graph-config%40workspace%3Apackages%2Fsolhint-graph-config": - version: 0.0.0 - resolution: "solhint-plugin-graph@file:plugin#plugin::hash=37bdb1&locator=solhint-graph-config%40workspace%3Apackages%2Fsolhint-graph-config" - checksum: f77aeda80dc6f8bb93376c3b05e910874038e701793f7805e9937f0047e68d3ac8595d915a4cb12dd974c49851d2b0fdf94742b0b2865cd7bf7e3a630177dfea - languageName: node - linkType: hard +"solhint-plugin-graph@workspace:*, solhint-plugin-graph@workspace:^0.0.1, solhint-plugin-graph@workspace:packages/solhint-plugin-graph": + version: 0.0.0-use.local + resolution: "solhint-plugin-graph@workspace:packages/solhint-plugin-graph" + languageName: unknown + linkType: soft "solhint-plugin-prettier@npm:^0.1.0": version: 0.1.0 From 7aa37984931aa5686721df975cdd8d71f37edb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 20 May 2024 14:23:47 -0300 Subject: [PATCH 023/277] chore: move data service framework, rework file structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/contracts/SimpleTest.sol | 10 ------ .../contracts/data-service/DataService.sol | 4 +-- .../data-service/DataServiceStorage.sol | 0 .../contracts/data-service/GraphDirectory.sol | 2 +- .../extensions/DataServiceFees.sol | 6 ++-- .../extensions/DataServiceFeesStorage.sol | 2 ++ .../extensions/DataServicePausable.sol | 0 .../extensions/DataServiceRescuable.sol | 2 +- .../extensions/IDataServiceFees.sol | 2 +- .../extensions/IDataServicePausable.sol | 2 +- .../extensions/IDataServiceRescuable.sol | 2 +- .../libraries/ProvisionGetter.sol | 2 +- .../libraries/ProvisionTracker.sol | 12 ++++--- .../utilities/ProvisionManager.sol | 10 +++--- .../utilities/ProvisionManagerStorage.sol | 0 .../contracts/interfaces}/IDataService.sol | 2 +- .../contracts/interfaces/IGraphEscrow.sol | 0 .../contracts/interfaces/IGraphPayments.sol | 0 .../{ => interfaces}/IGraphToken.sol | 2 +- .../{ => interfaces}/IHorizonStaking.sol | 0 .../{ => interfaces}/IHorizonStakingBase.sol | 0 .../IHorizonStakingExtension.sol | 0 .../{ => interfaces}/IHorizonStakingTypes.sol | 0 .../contracts/{ => interfaces}/IManaged.sol | 0 .../IStakingBackwardsCompatibility.sol | 0 .../contracts/interfaces/ITAPVerifier.sol | 0 .../contracts}/libraries/Denominations.sol | 0 .../{utils => libraries}/LibFixedMath.sol | 0 .../{utils => libraries}/MathUtils.sol | 0 .../contracts}/libraries/PPMMath.sol | 0 .../{utils => libraries}/TokenUtils.sol | 2 +- .../contracts}/libraries/UintRange.sol | 0 .../payments/collectors}/TAPVerifier.sol | 2 +- .../{ => staking}/HorizonStaking.sol | 11 ++++--- .../{ => staking}/HorizonStakingExtension.sol | 13 ++++---- .../{ => staking}/HorizonStakingStorage.sol | 7 +++-- .../StakingBackwardsCompatibility.sol | 31 +++++++------------ .../libraries}/ExponentialRebates.sol | 4 +-- .../{ => staking/utilities}/Managed.sol | 5 +-- packages/horizon/scripts/deploy.ts | 28 ----------------- packages/horizon/test/HorizonStaking.t.sol | 12 +++---- packages/horizon/test/HorizonStaking.ts | 4 +-- packages/horizon/test/SimpleTest.t.sol | 17 ---------- packages/horizon/test/SimpleTest.ts | 23 -------------- .../contracts/DisputeManager.sol | 12 ++++--- .../contracts/SubgraphService.sol | 22 ++++++------- .../contracts/SubgraphServiceStorage.sol | 2 +- .../contracts/interfaces/ISubgraphService.sol | 4 +-- .../contracts/utilities/AllocationManager.sol | 26 ++++++++++------ .../contracts/utilities/Directory.sol | 2 +- packages/subgraph-service/package.json | 1 + packages/subgraph-service/remappings.txt | 1 + .../test/mocks/MockHorizonStaking.sol | 24 ++++++++------ yarn.lock | 3 +- 54 files changed, 127 insertions(+), 189 deletions(-) delete mode 100644 packages/horizon/contracts/SimpleTest.sol rename packages/{subgraph-service => horizon}/contracts/data-service/DataService.sol (96%) rename packages/{subgraph-service => horizon}/contracts/data-service/DataServiceStorage.sol (100%) rename packages/{subgraph-service => horizon}/contracts/data-service/GraphDirectory.sol (96%) rename packages/{subgraph-service => horizon}/contracts/data-service/extensions/DataServiceFees.sol (98%) rename packages/{subgraph-service => horizon}/contracts/data-service/extensions/DataServiceFeesStorage.sol (96%) rename packages/{subgraph-service => horizon}/contracts/data-service/extensions/DataServicePausable.sol (100%) rename packages/{subgraph-service => horizon}/contracts/data-service/extensions/DataServiceRescuable.sol (97%) rename packages/{subgraph-service => horizon}/contracts/data-service/extensions/IDataServiceFees.sol (91%) rename packages/{subgraph-service => horizon}/contracts/data-service/extensions/IDataServicePausable.sol (73%) rename packages/{subgraph-service => horizon}/contracts/data-service/extensions/IDataServiceRescuable.sol (79%) rename packages/{subgraph-service => horizon}/contracts/data-service/libraries/ProvisionGetter.sol (87%) rename packages/{subgraph-service => horizon}/contracts/data-service/libraries/ProvisionTracker.sol (82%) rename packages/{subgraph-service => horizon}/contracts/data-service/utilities/ProvisionManager.sol (95%) rename packages/{subgraph-service => horizon}/contracts/data-service/utilities/ProvisionManagerStorage.sol (100%) rename packages/{subgraph-service/contracts/data-service => horizon/contracts/interfaces}/IDataService.sol (99%) rename packages/{subgraph-service => horizon}/contracts/interfaces/IGraphEscrow.sol (100%) rename packages/{subgraph-service => horizon}/contracts/interfaces/IGraphPayments.sol (100%) rename packages/horizon/contracts/{ => interfaces}/IGraphToken.sol (93%) rename packages/horizon/contracts/{ => interfaces}/IHorizonStaking.sol (100%) rename packages/horizon/contracts/{ => interfaces}/IHorizonStakingBase.sol (100%) rename packages/horizon/contracts/{ => interfaces}/IHorizonStakingExtension.sol (100%) rename packages/horizon/contracts/{ => interfaces}/IHorizonStakingTypes.sol (100%) rename packages/horizon/contracts/{ => interfaces}/IManaged.sol (100%) rename packages/horizon/contracts/{ => interfaces}/IStakingBackwardsCompatibility.sol (100%) rename packages/{subgraph-service => horizon}/contracts/interfaces/ITAPVerifier.sol (100%) rename packages/{subgraph-service/contracts/data-service => horizon/contracts}/libraries/Denominations.sol (100%) rename packages/horizon/contracts/{utils => libraries}/LibFixedMath.sol (100%) rename packages/horizon/contracts/{utils => libraries}/MathUtils.sol (100%) rename packages/{subgraph-service/contracts/data-service => horizon/contracts}/libraries/PPMMath.sol (100%) rename packages/horizon/contracts/{utils => libraries}/TokenUtils.sol (96%) rename packages/{subgraph-service/contracts/data-service => horizon/contracts}/libraries/UintRange.sol (100%) rename packages/{subgraph-service/contracts => horizon/contracts/payments/collectors}/TAPVerifier.sol (99%) rename packages/horizon/contracts/{ => staking}/HorizonStaking.sol (99%) rename packages/horizon/contracts/{ => staking}/HorizonStakingExtension.sol (97%) rename packages/horizon/contracts/{ => staking}/HorizonStakingStorage.sol (96%) rename packages/horizon/contracts/{ => staking}/StakingBackwardsCompatibility.sol (96%) rename packages/horizon/contracts/{utils => staking/libraries}/ExponentialRebates.sol (96%) rename packages/horizon/contracts/{ => staking/utilities}/Managed.sol (96%) delete mode 100644 packages/horizon/scripts/deploy.ts delete mode 100644 packages/horizon/test/SimpleTest.t.sol delete mode 100644 packages/horizon/test/SimpleTest.ts diff --git a/packages/horizon/contracts/SimpleTest.sol b/packages/horizon/contracts/SimpleTest.sol deleted file mode 100644 index 5cc28d9cc..000000000 --- a/packages/horizon/contracts/SimpleTest.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.4.0 <0.9.0; - -import { Test } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; - -contract SimpleTest is Test { - function test() external pure returns (uint256) { - return 42; - } -} diff --git a/packages/subgraph-service/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol similarity index 96% rename from packages/subgraph-service/contracts/data-service/DataService.sol rename to packages/horizon/contracts/data-service/DataService.sol index 52f1e25b5..f256cbba7 100644 --- a/packages/subgraph-service/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IDataService } from "./IDataService.sol"; +import { IDataService } from "../interfaces/IDataService.sol"; -import { GraphDirectory } from "./GraphDirectory.sol"; import { DataServiceV1Storage } from "./DataServiceStorage.sol"; +import { GraphDirectory } from "./GraphDirectory.sol"; import { ProvisionManager } from "./utilities/ProvisionManager.sol"; /** diff --git a/packages/subgraph-service/contracts/data-service/DataServiceStorage.sol b/packages/horizon/contracts/data-service/DataServiceStorage.sol similarity index 100% rename from packages/subgraph-service/contracts/data-service/DataServiceStorage.sol rename to packages/horizon/contracts/data-service/DataServiceStorage.sol diff --git a/packages/subgraph-service/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol similarity index 96% rename from packages/subgraph-service/contracts/data-service/GraphDirectory.sol rename to packages/horizon/contracts/data-service/GraphDirectory.sol index f35a7a663..b79d7de52 100644 --- a/packages/subgraph-service/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; -import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; // import { IGraphTokenGateway } from "@graphprotocol/contracts/contracts/gateway/IGraphTokenGateway.sol"; import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol similarity index 98% rename from packages/subgraph-service/contracts/data-service/extensions/DataServiceFees.sol rename to packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 583f01efa..3978d9a48 100644 --- a/packages/subgraph-service/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -4,11 +4,11 @@ pragma solidity ^0.8.24; import { IDataServiceFees } from "./IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; +import { ProvisionTracker } from "../libraries/ProvisionTracker.sol"; + import { DataService } from "../DataService.sol"; import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol"; -import { ProvisionTracker } from "../libraries/ProvisionTracker.sol"; - abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDataServiceFees { using ProvisionTracker for mapping(address => uint256); @@ -66,7 +66,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat uint256 _tokens, uint256 _unlockTimestamp ) internal { - feesProvisionTracker[_feeType].lock(GRAPH_STAKING, _serviceProvider, _tokens); + feesProvisionTracker[_feeType].lock(GRAPH_STAKING, _serviceProvider, _tokens, delegationRatio); StakeClaimsList storage claimsList = claimsLists[_feeType][_serviceProvider]; bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol similarity index 96% rename from packages/subgraph-service/contracts/data-service/extensions/DataServiceFeesStorage.sol rename to packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 4296a952a..d64f99239 100644 --- a/packages/subgraph-service/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -15,6 +15,8 @@ abstract contract DataServiceFeesV1Storage { mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => IDataServiceFees.StakeClaimsList list)) public claimsLists; + uint32 public delegationRatio; + /// @dev Gap to allow adding variables in future upgrades uint256[50] private __gap; } diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol similarity index 100% rename from packages/subgraph-service/contracts/data-service/extensions/DataServicePausable.sol rename to packages/horizon/contracts/data-service/extensions/DataServicePausable.sol diff --git a/packages/subgraph-service/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol similarity index 97% rename from packages/subgraph-service/contracts/data-service/extensions/DataServiceRescuable.sol rename to packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 7e6120783..76a25162a 100644 --- a/packages/subgraph-service/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -6,7 +6,7 @@ import { IDataServiceRescuable } from "./IDataServiceRescuable.sol"; import { DataService } from "../DataService.sol"; -import { Denominations } from "../libraries/Denominations.sol"; +import { Denominations } from "../../libraries/Denominations.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** diff --git a/packages/subgraph-service/contracts/data-service/extensions/IDataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol similarity index 91% rename from packages/subgraph-service/contracts/data-service/extensions/IDataServiceFees.sol rename to packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol index 36caf73f1..fe75755fe 100644 --- a/packages/subgraph-service/contracts/data-service/extensions/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IDataService } from "../IDataService.sol"; +import { IDataService } from "../../interfaces/IDataService.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; interface IDataServiceFees is IDataService { diff --git a/packages/subgraph-service/contracts/data-service/extensions/IDataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol similarity index 73% rename from packages/subgraph-service/contracts/data-service/extensions/IDataServicePausable.sol rename to packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol index 5b2940d6c..302e8a67e 100644 --- a/packages/subgraph-service/contracts/data-service/extensions/IDataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IDataService } from "../IDataService.sol"; +import { IDataService } from "../../interfaces/IDataService.sol"; interface IDataServicePausable is IDataService { function pause() external; diff --git a/packages/subgraph-service/contracts/data-service/extensions/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol similarity index 79% rename from packages/subgraph-service/contracts/data-service/extensions/IDataServiceRescuable.sol rename to packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol index 36ad6d68f..ee379315c 100644 --- a/packages/subgraph-service/contracts/data-service/extensions/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IDataService } from "../IDataService.sol"; +import { IDataService } from "../../interfaces/IDataService.sol"; interface IDataServiceRescuable is IDataService { function rescueGRT(address to, uint256 amount) external; diff --git a/packages/subgraph-service/contracts/data-service/libraries/ProvisionGetter.sol b/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol similarity index 87% rename from packages/subgraph-service/contracts/data-service/libraries/ProvisionGetter.sol rename to packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol index 4de039012..6fdf1e2c4 100644 --- a/packages/subgraph-service/contracts/data-service/libraries/ProvisionGetter.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; library ProvisionGetter { using ProvisionGetter for IHorizonStaking.Provision; diff --git a/packages/subgraph-service/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol similarity index 82% rename from packages/subgraph-service/contracts/data-service/libraries/ProvisionTracker.sol rename to packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index 216bbe3dc..f0acc7f89 100644 --- a/packages/subgraph-service/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; library ProvisionTracker { error ProvisionTrackerInsufficientTokens(uint256 tokensAvailable, uint256 tokensRequired); @@ -10,12 +10,13 @@ library ProvisionTracker { mapping(address => uint256) storage self, IHorizonStaking graphStaking, address serviceProvider, - uint256 tokens + uint256 tokens, + uint32 delegationRatio ) internal { if (tokens == 0) return; uint256 tokensRequired = self[serviceProvider] + tokens; - uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this)); + uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this), delegationRatio); if (tokensRequired > tokensAvailable) { revert ProvisionTrackerInsufficientTokens(tokensAvailable, tokensRequired); } @@ -34,9 +35,10 @@ library ProvisionTracker { function getTokensFree( mapping(address => uint256) storage self, IHorizonStaking graphStaking, - address serviceProvider + address serviceProvider, + uint32 delegationRatio ) internal view returns (uint256) { - uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this)); + uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this), delegationRatio); if (tokensAvailable >= self[serviceProvider]) return tokensAvailable - self[serviceProvider]; else return 0; } diff --git a/packages/subgraph-service/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol similarity index 95% rename from packages/subgraph-service/contracts/data-service/utilities/ProvisionManager.sol rename to packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 581cff131..dd9d2677f 100644 --- a/packages/subgraph-service/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; + +import { ProvisionGetter } from "../libraries/ProvisionGetter.sol"; +import { UintRange } from "../../libraries/UintRange.sol"; import { GraphDirectory } from "../GraphDirectory.sol"; import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; -import { ProvisionGetter } from "../libraries/ProvisionGetter.sol"; -import { UintRange } from "../libraries/UintRange.sol"; - abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage { using ProvisionGetter for IHorizonStaking; using UintRange for uint256; @@ -50,7 +50,7 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage function _checkAndAcceptProvision(address _serviceProvider) internal virtual { _checkProvisionParameters(_serviceProvider); - GRAPH_STAKING.acceptProvision(_serviceProvider); + GRAPH_STAKING.acceptProvisionParameters(_serviceProvider); } // -- Provision Parameters: setters -- diff --git a/packages/subgraph-service/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol similarity index 100% rename from packages/subgraph-service/contracts/data-service/utilities/ProvisionManagerStorage.sol rename to packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol diff --git a/packages/subgraph-service/contracts/data-service/IDataService.sol b/packages/horizon/contracts/interfaces/IDataService.sol similarity index 99% rename from packages/subgraph-service/contracts/data-service/IDataService.sol rename to packages/horizon/contracts/interfaces/IDataService.sol index 0e598b2cb..4064d4444 100644 --- a/packages/subgraph-service/contracts/data-service/IDataService.sol +++ b/packages/horizon/contracts/interfaces/IDataService.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IGraphPayments } from "./IGraphPayments.sol"; /** * @title Interface of the base {DataService} contract as defined by the Graph Horizon specification. diff --git a/packages/subgraph-service/contracts/interfaces/IGraphEscrow.sol b/packages/horizon/contracts/interfaces/IGraphEscrow.sol similarity index 100% rename from packages/subgraph-service/contracts/interfaces/IGraphEscrow.sol rename to packages/horizon/contracts/interfaces/IGraphEscrow.sol diff --git a/packages/subgraph-service/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol similarity index 100% rename from packages/subgraph-service/contracts/interfaces/IGraphPayments.sol rename to packages/horizon/contracts/interfaces/IGraphPayments.sol diff --git a/packages/horizon/contracts/IGraphToken.sol b/packages/horizon/contracts/interfaces/IGraphToken.sol similarity index 93% rename from packages/horizon/contracts/IGraphToken.sol rename to packages/horizon/contracts/interfaces/IGraphToken.sol index fd0b0a553..27f68a0d2 100644 --- a/packages/horizon/contracts/IGraphToken.sol +++ b/packages/horizon/contracts/interfaces/IGraphToken.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IGraphToken is IERC20 { // -- Mint and Burn -- diff --git a/packages/horizon/contracts/IHorizonStaking.sol b/packages/horizon/contracts/interfaces/IHorizonStaking.sol similarity index 100% rename from packages/horizon/contracts/IHorizonStaking.sol rename to packages/horizon/contracts/interfaces/IHorizonStaking.sol diff --git a/packages/horizon/contracts/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol similarity index 100% rename from packages/horizon/contracts/IHorizonStakingBase.sol rename to packages/horizon/contracts/interfaces/IHorizonStakingBase.sol diff --git a/packages/horizon/contracts/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol similarity index 100% rename from packages/horizon/contracts/IHorizonStakingExtension.sol rename to packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol diff --git a/packages/horizon/contracts/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol similarity index 100% rename from packages/horizon/contracts/IHorizonStakingTypes.sol rename to packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol diff --git a/packages/horizon/contracts/IManaged.sol b/packages/horizon/contracts/interfaces/IManaged.sol similarity index 100% rename from packages/horizon/contracts/IManaged.sol rename to packages/horizon/contracts/interfaces/IManaged.sol diff --git a/packages/horizon/contracts/IStakingBackwardsCompatibility.sol b/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol similarity index 100% rename from packages/horizon/contracts/IStakingBackwardsCompatibility.sol rename to packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol diff --git a/packages/subgraph-service/contracts/interfaces/ITAPVerifier.sol b/packages/horizon/contracts/interfaces/ITAPVerifier.sol similarity index 100% rename from packages/subgraph-service/contracts/interfaces/ITAPVerifier.sol rename to packages/horizon/contracts/interfaces/ITAPVerifier.sol diff --git a/packages/subgraph-service/contracts/data-service/libraries/Denominations.sol b/packages/horizon/contracts/libraries/Denominations.sol similarity index 100% rename from packages/subgraph-service/contracts/data-service/libraries/Denominations.sol rename to packages/horizon/contracts/libraries/Denominations.sol diff --git a/packages/horizon/contracts/utils/LibFixedMath.sol b/packages/horizon/contracts/libraries/LibFixedMath.sol similarity index 100% rename from packages/horizon/contracts/utils/LibFixedMath.sol rename to packages/horizon/contracts/libraries/LibFixedMath.sol diff --git a/packages/horizon/contracts/utils/MathUtils.sol b/packages/horizon/contracts/libraries/MathUtils.sol similarity index 100% rename from packages/horizon/contracts/utils/MathUtils.sol rename to packages/horizon/contracts/libraries/MathUtils.sol diff --git a/packages/subgraph-service/contracts/data-service/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol similarity index 100% rename from packages/subgraph-service/contracts/data-service/libraries/PPMMath.sol rename to packages/horizon/contracts/libraries/PPMMath.sol diff --git a/packages/horizon/contracts/utils/TokenUtils.sol b/packages/horizon/contracts/libraries/TokenUtils.sol similarity index 96% rename from packages/horizon/contracts/utils/TokenUtils.sol rename to packages/horizon/contracts/libraries/TokenUtils.sol index 7bfc7203c..07b267451 100644 --- a/packages/horizon/contracts/utils/TokenUtils.sol +++ b/packages/horizon/contracts/libraries/TokenUtils.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; -import { IGraphToken } from "../IGraphToken.sol"; +import { IGraphToken } from "../interfaces/IGraphToken.sol"; /** * @title TokenUtils library diff --git a/packages/subgraph-service/contracts/data-service/libraries/UintRange.sol b/packages/horizon/contracts/libraries/UintRange.sol similarity index 100% rename from packages/subgraph-service/contracts/data-service/libraries/UintRange.sol rename to packages/horizon/contracts/libraries/UintRange.sol diff --git a/packages/subgraph-service/contracts/TAPVerifier.sol b/packages/horizon/contracts/payments/collectors/TAPVerifier.sol similarity index 99% rename from packages/subgraph-service/contracts/TAPVerifier.sol rename to packages/horizon/contracts/payments/collectors/TAPVerifier.sol index e7b3d5a7f..735cc38a0 100644 --- a/packages/subgraph-service/contracts/TAPVerifier.sol +++ b/packages/horizon/contracts/payments/collectors/TAPVerifier.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { ITAPVerifier } from "./interfaces/ITAPVerifier.sol"; +import { ITAPVerifier } from "../../interfaces/ITAPVerifier.sol"; import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; diff --git a/packages/horizon/contracts/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol similarity index 99% rename from packages/horizon/contracts/HorizonStaking.sol rename to packages/horizon/contracts/staking/HorizonStaking.sol index 7b97260be..883e1f611 100644 --- a/packages/horizon/contracts/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -3,12 +3,13 @@ pragma solidity 0.8.24; import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; +import { IHorizonStakingBase } from "../interfaces/IHorizonStakingBase.sol"; +import { IGraphToken } from "../interfaces/IGraphToken.sol"; -import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; -import { TokenUtils } from "./utils/TokenUtils.sol"; -import { MathUtils } from "./utils/MathUtils.sol"; -import { Managed } from "./Managed.sol"; -import { IGraphToken } from "./IGraphToken.sol"; +import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { MathUtils } from "../libraries/MathUtils.sol"; + +import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; /** diff --git a/packages/horizon/contracts/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol similarity index 97% rename from packages/horizon/contracts/HorizonStakingExtension.sol rename to packages/horizon/contracts/staking/HorizonStakingExtension.sol index 1ec8b2c45..0183e73f9 100644 --- a/packages/horizon/contracts/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -2,11 +2,13 @@ pragma solidity 0.8.24; -import { StakingBackwardsCompatibility } from "./StakingBackwardsCompatibility.sol"; import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; -import { IHorizonStakingExtension } from "./IHorizonStakingExtension.sol"; -import { MathUtils } from "./utils/MathUtils.sol"; +import { IHorizonStakingExtension } from "../interfaces/IHorizonStakingExtension.sol"; + +import { MathUtils } from "../libraries/MathUtils.sol"; + +import { StakingBackwardsCompatibility } from "./StakingBackwardsCompatibility.sol"; /** * @title L2Staking contract @@ -28,9 +30,8 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStaki constructor( address _controller, - address _subgraphDataServiceAddress, - address _exponentialRebates - ) StakingBackwardsCompatibility(_controller, _subgraphDataServiceAddress, _exponentialRebates) {} + address _subgraphDataServiceAddress + ) StakingBackwardsCompatibility(_controller, _subgraphDataServiceAddress) {} /** * @notice Receive ETH into the Staking contract: this will always revert diff --git a/packages/horizon/contracts/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol similarity index 96% rename from packages/horizon/contracts/HorizonStakingStorage.sol rename to packages/horizon/contracts/staking/HorizonStakingStorage.sol index 6506429a7..80e25f6ae 100644 --- a/packages/horizon/contracts/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -2,9 +2,10 @@ pragma solidity 0.8.24; -import { Managed } from "./Managed.sol"; -import { IStakingBackwardsCompatibility } from "./IStakingBackwardsCompatibility.sol"; -import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; +import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; +import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; + +import { Managed } from "./utilities/Managed.sol"; /** * @title HorizonStakingV1Storage diff --git a/packages/horizon/contracts/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol similarity index 96% rename from packages/horizon/contracts/StakingBackwardsCompatibility.sol rename to packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 6e6261bd4..0d8c2749e 100644 --- a/packages/horizon/contracts/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -2,20 +2,20 @@ pragma solidity 0.8.24; -import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; +import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; +import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; +import { IGraphToken } from "../interfaces/IGraphToken.sol"; +import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; + +import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { MathUtils } from "../libraries/MathUtils.sol"; +import { ExponentialRebates } from "./libraries/ExponentialRebates.sol"; import { Multicall } from "@graphprotocol/contracts/contracts/base/Multicall.sol"; import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; -import { TokenUtils } from "./utils/TokenUtils.sol"; -import { IGraphToken } from "./IGraphToken.sol"; +import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; -import { MathUtils } from "./utils/MathUtils.sol"; -import { Managed } from "./Managed.sol"; -import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; -import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; -import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; -import { ExponentialRebates } from "./utils/ExponentialRebates.sol"; -import { IStakingBackwardsCompatibility } from "./IStakingBackwardsCompatibility.sol"; /** * @title Base Staking contract @@ -38,15 +38,8 @@ abstract contract StakingBackwardsCompatibility is address public immutable SUBGRAPH_DATA_SERVICE_ADDRESS; - address public immutable EXPONENTIAL_REBATES_ADDRESS; - - constructor( - address _controller, - address _subgraphDataServiceAddress, - address _exponentialRebatesAddress - ) Managed(_controller) { + constructor(address _controller, address _subgraphDataServiceAddress) Managed(_controller) { SUBGRAPH_DATA_SERVICE_ADDRESS = _subgraphDataServiceAddress; - EXPONENTIAL_REBATES_ADDRESS = _exponentialRebatesAddress; } /** @@ -128,7 +121,7 @@ abstract contract StakingBackwardsCompatibility is // No rebates if indexer has no stake or if lambda is zero uint256 newRebates = (alloc.tokens == 0 || __DEPRECATED_lambdaNumerator == 0) ? 0 - : ExponentialRebates(EXPONENTIAL_REBATES_ADDRESS).exponentialRebates( + : ExponentialRebates.exponentialRebates( alloc.collectedFees, alloc.tokens, __DEPRECATED_alphaNumerator, diff --git a/packages/horizon/contracts/utils/ExponentialRebates.sol b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol similarity index 96% rename from packages/horizon/contracts/utils/ExponentialRebates.sol rename to packages/horizon/contracts/staking/libraries/ExponentialRebates.sol index d53efdca3..50579cafb 100644 --- a/packages/horizon/contracts/utils/ExponentialRebates.sol +++ b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; -import { LibFixedMath } from "./LibFixedMath.sol"; +import { LibFixedMath } from "../../libraries/LibFixedMath.sol"; /** * @title ExponentialRebates contract @@ -10,7 +10,7 @@ import { LibFixedMath } from "./LibFixedMath.sol"; * @dev This is only used for backwards compatibility in HorizonStaking, and should * be removed after the transition period. */ -contract ExponentialRebates { +library ExponentialRebates { /// @dev Maximum value of the exponent for which to compute the exponential before clamping to zero. uint32 private constant MAX_EXPONENT = 15; diff --git a/packages/horizon/contracts/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol similarity index 96% rename from packages/horizon/contracts/Managed.sol rename to packages/horizon/contracts/staking/utilities/Managed.sol index 858156bbd..685c18184 100644 --- a/packages/horizon/contracts/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -3,8 +3,9 @@ pragma solidity 0.8.24; import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; -import { IManaged } from "./IManaged.sol"; -import { GraphDirectory } from "./GraphDirectory.sol"; +import { IManaged } from "../../interfaces/IManaged.sol"; + +import { GraphDirectory } from "../../GraphDirectory.sol"; /** * @title Graph Managed contract diff --git a/packages/horizon/scripts/deploy.ts b/packages/horizon/scripts/deploy.ts deleted file mode 100644 index cf87ff10f..000000000 --- a/packages/horizon/scripts/deploy.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ethers } from 'hardhat' - -async function main() { - const currentTimestampInSeconds = Math.round(Date.now() / 1000) - const unlockTime = currentTimestampInSeconds + 60 - - const lockedAmount = ethers.parseEther('0.001') - const a = 1 - console.log(a) - const lock = await ethers.deployContract('Lock', [unlockTime], { - value: lockedAmount, - }) - - await lock.waitForDeployment() - - console.log( - `Lock with ${ethers.formatEther( - lockedAmount, - )}ETH and unlock timestamp ${unlockTime} deployed to ${typeof lock.target == 'string' ? lock.target : ''}`, - ) -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error) - process.exitCode = 1 -}) diff --git a/packages/horizon/test/HorizonStaking.t.sol b/packages/horizon/test/HorizonStaking.t.sol index 144b0c7a5..55088f0fe 100644 --- a/packages/horizon/test/HorizonStaking.t.sol +++ b/packages/horizon/test/HorizonStaking.t.sol @@ -3,14 +3,13 @@ pragma solidity 0.8.24; import "forge-std/Test.sol"; import "forge-std/console.sol"; -import { HorizonStaking } from "../contracts/HorizonStaking.sol"; +import { HorizonStaking } from "../contracts/staking/HorizonStaking.sol"; import { ControllerMock } from "../contracts/mocks/ControllerMock.sol"; -import { HorizonStakingExtension } from "../contracts/HorizonStakingExtension.sol"; -import { ExponentialRebates } from "../contracts/utils/ExponentialRebates.sol"; -import { IHorizonStaking } from "../contracts/IHorizonStaking.sol"; +import { HorizonStakingExtension } from "../contracts/staking/HorizonStakingExtension.sol"; +import { ExponentialRebates } from "../contracts/staking/libraries/ExponentialRebates.sol"; +import { IHorizonStaking } from "../contracts/interfaces/IHorizonStaking.sol"; contract HorizonStakingTest is Test { - ExponentialRebates rebates; HorizonStakingExtension ext; IHorizonStaking staking; ControllerMock controller; @@ -19,8 +18,7 @@ contract HorizonStakingTest is Test { console.log("Deploying Controller mock"); controller = new ControllerMock(address(0x1)); console.log("Deploying HorizonStaking"); - rebates = new ExponentialRebates(); - ext = new HorizonStakingExtension(address(controller), address(0x1), address(rebates)); + ext = new HorizonStakingExtension(address(controller), address(0x1)); staking = IHorizonStaking(address(new HorizonStaking(address(controller), address(ext), address(0x1)))); } diff --git a/packages/horizon/test/HorizonStaking.ts b/packages/horizon/test/HorizonStaking.ts index 6f6e1ad88..28eb281f7 100644 --- a/packages/horizon/test/HorizonStaking.ts +++ b/packages/horizon/test/HorizonStaking.ts @@ -16,8 +16,8 @@ describe('HorizonStaking', function () { const ExponentialRebates = await ethers.getContractFactory('ExponentialRebates') const exponentialRebates = await ExponentialRebates.deploy() await exponentialRebates.waitForDeployment() - const HorizonStakingExtension = await ethers.getContractFactory('HorizonStakingExtension') - const horizonStakingExtension = await HorizonStakingExtension.deploy(controller.target, ZeroAddress, exponentialRebates.target) + const HorizonStakingExtension = await ethers.getContractFactory('HorizonStakingExtension', { libraries: { ExponentialRebates: exponentialRebates.target } }) + const horizonStakingExtension = await HorizonStakingExtension.deploy(controller.target, ZeroAddress) await horizonStakingExtension.waitForDeployment() const HorizonStaking = await ethers.getContractFactory('HorizonStaking') const horizonStakingContract = await HorizonStaking.deploy(controller.target, horizonStakingExtension.target, ZeroAddress) diff --git a/packages/horizon/test/SimpleTest.t.sol b/packages/horizon/test/SimpleTest.t.sol deleted file mode 100644 index b130e5d34..000000000 --- a/packages/horizon/test/SimpleTest.t.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.10; - -import "forge-std/Test.sol"; -import { SimpleTest } from "../contracts/SimpleTest.sol"; - -contract ContractTest is Test { - SimpleTest simpleTest; - - function setUp() public { - simpleTest = new SimpleTest(); - } - - function test_NumberIs42() public { - assertEq(simpleTest.test(), 42); - } -} diff --git a/packages/horizon/test/SimpleTest.ts b/packages/horizon/test/SimpleTest.ts deleted file mode 100644 index cfcfb1443..000000000 --- a/packages/horizon/test/SimpleTest.ts +++ /dev/null @@ -1,23 +0,0 @@ -import hardhat from 'hardhat' - -import { expect } from 'chai' -import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' - -const ethers = hardhat.ethers - -describe('SimpleTest', function () { - async function deployFixture() { - const [owner] = await ethers.getSigners() - const SimpleTest = await ethers.getContractFactory('SimpleTest') - const simpleTest = await SimpleTest.deploy() - return { simpleTest, owner } - } - - describe('Deployment', function () { - it('Should return 42', async function () { - const { simpleTest } = await loadFixture(deployFixture) - - expect(await simpleTest.test()).to.equal(42) - }) - }) -}) diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index dc5f785f2..e74ba0f0b 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -2,19 +2,19 @@ pragma solidity ^0.8.24; pragma abicoder v2; -import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; -import { GraphDirectory } from "./data-service/GraphDirectory.sol"; +import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; import { AttestationManager } from "./utilities/AttestationManager.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { Allocation } from "./libraries/Allocation.sol"; -import { PPMMath } from "./data-service/libraries/PPMMath.sol"; import { Attestation } from "./libraries/Attestation.sol"; /* @@ -670,7 +670,11 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM function _slashIndexer(address _indexer, uint256 _slashAmount) private returns (uint256 rewardsAmount) { // Get slashable amount for indexer IHorizonStaking.Provision memory provision = GRAPH_STAKING.getProvision(_indexer, address(subgraphService)); - uint256 totalProvisionTokens = provision.tokens + provision.delegatedTokens; // slashable tokens + IHorizonStaking.DelegationPool memory pool = GRAPH_STAKING.getDelegationPool( + _indexer, + address(subgraphService) + ); + uint256 totalProvisionTokens = provision.tokens + pool.tokens; // slashable tokens // Get slash amount uint256 maxSlashAmount = uint256(maxSlashingPercentage).mulPPM(totalProvisionTokens); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 9489373ab..896314bf8 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { ITAPVerifier } from "@graphprotocol/horizon/contracts/interfaces/ITAPVerifier.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; -import { ITAPVerifier } from "./interfaces/ITAPVerifier.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { DataService } from "./data-service/DataService.sol"; -import { DataServicePausable } from "./data-service/extensions/DataServicePausable.sol"; -import { DataServiceRescuable } from "./data-service/extensions/DataServiceRescuable.sol"; -import { DataServiceFees } from "./data-service/extensions/DataServiceFees.sol"; +import { DataServicePausable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServicePausable.sol"; +import { DataService } from "@graphprotocol/horizon/contracts/data-service/DataService.sol"; +import { DataServiceRescuable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServiceRescuable.sol"; +import { DataServiceFees } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServiceFees.sol"; import { Directory } from "./utilities/Directory.sol"; import { AllocationManager } from "./utilities/AllocationManager.sol"; import { SubgraphServiceV1Storage } from "./SubgraphServiceStorage.sol"; -import { PPMMath } from "./data-service/libraries/PPMMath.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; @@ -111,7 +111,7 @@ contract SubgraphService is data, (bytes32, uint256, address, bytes) ); - _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof); + _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof, delegationRatio); emit ServiceStarted(indexer); } @@ -138,7 +138,7 @@ contract SubgraphService is address allocationId, uint256 tokens ) external onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { - _resizeAllocation(allocationId, tokens); + _resizeAllocation(allocationId, tokens, delegationRatio); } // TODO: Does this design allow custom payment types?! @@ -184,8 +184,8 @@ contract SubgraphService is return legacyAllocations[allocationId]; } - function encodeAllocationProof(address _indexer, address _allocationId) external view returns (bytes32) { - return _encodeAllocationProof(_indexer, _allocationId); + function encodeAllocationProof(address indexer, address allocationId) external view returns (bytes32) { + return _encodeAllocationProof(indexer, allocationId); } // -- Data service parameter getters -- diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 27ebc13ff..c67702428 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; -import { IGraphPayments } from "./interfaces/IGraphPayments.sol"; abstract contract SubgraphServiceV1Storage { /// @notice Service providers registered in the data service diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index ab62a3d84..17dd7019c 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IDataServiceFees } from "../data-service/extensions/IDataServiceFees.sol"; +import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/extensions/IDataServiceFees.sol"; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; @@ -28,5 +28,5 @@ interface ISubgraphService is IDataServiceFees { function getLegacyAllocation(address allocationId) external view returns (LegacyAllocation.State memory); - function encodeAllocationProof(address _indexer, address _allocationId) external view returns (bytes32); + function encodeAllocationProof(address indexer, address allocationId) external view returns (bytes32); } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index bcd7f1097..3e43fc0fb 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; -import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; -import { PPMMath } from "../data-service/libraries/PPMMath.sol"; -import { ProvisionTracker } from "../data-service/libraries/ProvisionTracker.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManagerV1Storage { using ProvisionTracker for mapping(address => uint256); @@ -89,7 +89,8 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager address _allocationId, bytes32 _subgraphDeploymentId, uint256 _tokens, - bytes memory _allocationProof + bytes memory _allocationProof, + uint32 __delegationRatio ) internal returns (Allocation.State memory) { if (_allocationId == address(0)) revert AllocationManagerInvalidAllocationId(); @@ -108,7 +109,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager ); // Check that the indexer has enough tokens available - allocationProvisionTracker.lock(GRAPH_STAKING, _indexer, _tokens); + allocationProvisionTracker.lock(GRAPH_STAKING, _indexer, _tokens, delegationRatio); // Update total allocated tokens for the subgraph deployment subgraphAllocatedTokens[allocation.subgraphDeploymentId] = @@ -146,13 +147,14 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Distribute rewards to delegators // TODO: remove the uint8 cast when PRs are merged - uint256 delegatorCut = GRAPH_STAKING.getDelegationCut( + uint256 delegatorCut = GRAPH_STAKING.getDelegationFeeCut( allocation.indexer, + address(this), uint8(IGraphPayments.PaymentTypes.IndexingFee) ); uint256 tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); GRAPH_TOKEN.approve(address(GRAPH_STAKING), tokensDelegationRewards); - GRAPH_STAKING.addToDelegationPool(allocation.indexer, tokensDelegationRewards); + GRAPH_STAKING.addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); // Distribute rewards to indexer uint256 tokensIndexerRewards = tokensRewards - tokensDelegationRewards; @@ -177,7 +179,11 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager return tokensRewards; } - function _resizeAllocation(address _allocationId, uint256 _tokens) internal returns (Allocation.State memory) { + function _resizeAllocation( + address _allocationId, + uint256 _tokens, + uint3 _ _delegationRatio + ) internal returns (Allocation.State memory) { Allocation.State memory allocation = allocations.get(_allocationId); // Exit early if the allocation size is the same @@ -188,7 +194,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Update provision tracker uint256 oldTokens = allocation.tokens; if (_tokens > oldTokens) { - allocationProvisionTracker.lock(GRAPH_STAKING, allocation.indexer, _tokens - oldTokens); + allocationProvisionTracker.lock(GRAPH_STAKING, allocation.indexer, _tokens - oldTokens, delegationRatio); } else { allocationProvisionTracker.release(allocation.indexer, oldTokens - _tokens); } diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index cd87de102..bc452f072 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { ITAPVerifier } from "../interfaces/ITAPVerifier.sol"; +import { ITAPVerifier } from "@graphprotocol/horizon/contracts/interfaces/ITAPVerifier.sol"; import { IDisputeManager } from "../interfaces/IDisputeManager.sol"; import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index 144263417..8ad66358e 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -14,6 +14,7 @@ }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", + "@graphprotocol/horizon": "workspace:^0.0.1", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", "@nomicfoundation/hardhat-foundry": "^1.1.1", diff --git a/packages/subgraph-service/remappings.txt b/packages/subgraph-service/remappings.txt index 1bd6482cd..d9bed44ec 100644 --- a/packages/subgraph-service/remappings.txt +++ b/packages/subgraph-service/remappings.txt @@ -1,4 +1,5 @@ @graphprotocol/contracts/=node_modules/@graphprotocol/contracts/ +@graphprotocol/horizon/=node_modules/@graphprotocol/horizon/ forge-std/=lib/forge-std/src/ ds-test/=lib/forge-std/lib/ds-test/src/ eth-gas-reporter/=node_modules/eth-gas-reporter/ diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index bd67a980c..b8f722bcf 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -3,10 +3,11 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; -import { IHorizonStaking } from "@graphprotocol/contracts/contracts/staking/IHorizonStaking.sol"; +import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; +import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStakingTypes.sol"; import { MockGRTToken } from "./MockGRTToken.sol"; -contract MockHorizonStaking is IHorizonStaking { +contract MockHorizonStaking { mapping (address verifier => mapping (address serviceProvider => IHorizonStaking.Provision provision)) public _provisions; MockGRTToken public grtToken; @@ -22,15 +23,18 @@ contract MockHorizonStaking is IHorizonStaking { // create a provision function provision(uint256 tokens, address verifier, uint32 maxVerifierCut, uint64 thawingPeriod) external { - IHorizonStaking.Provision memory newProvision = IHorizonStaking.Provision({ - serviceProvider: msg.sender, + IHorizonStaking.Provision memory newProvision = IHorizonStakingTypes.Provision({ tokens: tokens, - delegatedTokens: 0, tokensThawing: 0, - createdAt: uint64(block.timestamp), - verifier: verifier, + sharesThawing: 0, maxVerifierCut: maxVerifierCut, - thawingPeriod: thawingPeriod + thawingPeriod: thawingPeriod, + createdAt: uint64(block.timestamp), + firstThawRequestId: bytes32(0), + lastThawRequestId: bytes32(0), + nThawRequests: 0, + maxVerifierCutPending: maxVerifierCut, + thawingPeriodPending: thawingPeriod }); _provisions[verifier][msg.sender] = newProvision; } @@ -86,9 +90,9 @@ contract MockHorizonStaking is IHorizonStaking { return _provisions[verifier][serviceProvider].tokens; } - function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory) {} + function getServiceProvider(address serviceProvider) external view returns (IHorizonStaking.ServiceProvider memory) {} - function getProvision(address serviceProvider, address verifier) external view returns (Provision memory) { + function getProvision(address serviceProvider, address verifier) external view returns (IHorizonStaking.Provision memory) { return _provisions[verifier][serviceProvider]; } diff --git a/yarn.lock b/yarn.lock index bed525f83..c105ba53f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2909,7 +2909,7 @@ __metadata: languageName: unknown linkType: soft -"@graphprotocol/horizon@workspace:packages/horizon": +"@graphprotocol/horizon@workspace:^0.0.1, @graphprotocol/horizon@workspace:packages/horizon": version: 0.0.0-use.local resolution: "@graphprotocol/horizon@workspace:packages/horizon" dependencies: @@ -2999,6 +2999,7 @@ __metadata: resolution: "@graphprotocol/subgraph-service@workspace:packages/subgraph-service" dependencies: "@graphprotocol/contracts": "workspace:^7.0.0" + "@graphprotocol/horizon": "workspace:^0.0.1" "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.0" "@nomicfoundation/hardhat-ethers": "npm:^3.0.0" "@nomicfoundation/hardhat-foundry": "npm:^1.1.1" From c052943e1f35cb97ecc6ce6e2cc96ea3fb78140b Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Mon, 20 May 2024 14:30:08 -0300 Subject: [PATCH 024/277] chore: uint tests refactor --- packages/horizon/test/GraphBase.t.sol | 12 +- .../horizon/test/escrow/GraphEscrow.t.sol | 304 ++---------------- packages/horizon/test/escrow/collect.t.sol | 75 +++++ packages/horizon/test/escrow/collector.t.sol | 87 +++++ packages/horizon/test/escrow/deposit.t.sol | 53 +++ packages/horizon/test/escrow/thaw.t.sol | 34 ++ packages/horizon/test/escrow/withdraw.t.sol | 48 +++ .../horizon/test/payments/GraphPayments.t.sol | 4 +- .../horizon-staking/HorizonStaking.t.sol | 10 +- 9 files changed, 332 insertions(+), 295 deletions(-) create mode 100644 packages/horizon/test/escrow/collect.t.sol create mode 100644 packages/horizon/test/escrow/collector.t.sol create mode 100644 packages/horizon/test/escrow/deposit.t.sol create mode 100644 packages/horizon/test/escrow/thaw.t.sol create mode 100644 packages/horizon/test/escrow/withdraw.t.sol diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 5367dc0c1..b26bc14e1 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -57,6 +57,14 @@ abstract contract GraphBaseTest is Test, Constants { // Deploy protocol contracts deployProtocolContracts(); unpauseProtocol(); + + // Label contracts + vm.label({ account: address(controller), newLabel: "Controller" }); + vm.label({ account: address(token), newLabel: "GraphToken" }); + vm.label({ account: address(payments), newLabel: "GraphPayments" }); + vm.label({ account: address(escrow), newLabel: "GraphEscrow" }); + vm.label({ account: address(staking), newLabel: "HorizonStaking" }); + vm.label({ account: address(stakingExtension), newLabel: "HorizonStakingExtension" }); } function deployProtocolContracts() private { @@ -158,7 +166,9 @@ abstract contract GraphBaseTest is Test, Constants { function createUser(string memory name) private returns (address) { address user = makeAddr(name); - deal({ token: address(token), to: user, give: 10000 ether }); + vm.deal({ account: user, newBalance: 100 ether }); + deal({ token: address(token), to: user, give: type(uint256).max }); + vm.label({ account: user, newLabel: name }); return user; } diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index ced2cbd18..f420c1964 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -3,306 +3,38 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; -import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; +import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaking.t.sol"; -import { HorizonStaking_Shared_Test } from "../shared/horizon-staking/HorizonStaking.t.sol"; +contract GraphEscrowTest is HorizonStakingSharedTest { -contract GraphEscrowTest is HorizonStaking_Shared_Test { - - // Collector approve tests - - function testCollector_Approve() public { - vm.prank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - - (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); - assertEq(thawEndTimestamp, 0); - } - - // Collector thaw tests - - function testCollector_Thaw() public { - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - escrow.thawCollector(users.verifier); - vm.stopPrank(); - - (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); - assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); - } - - // Collector cancel thaw tests - - function testCollector_CancelThaw() public { - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - escrow.thawCollector(users.verifier); - vm.stopPrank(); - - (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); - assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); - - vm.prank(users.gateway); - escrow.cancelThawCollector(users.verifier); - - (authorized,, thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); - assertEq(thawEndTimestamp, 0); - } - - function testCollector_RevertWhen_CancelThawIsNotThawing() public { - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); - vm.expectRevert(expectedError); - escrow.cancelThawCollector(users.verifier); - vm.stopPrank(); - } - - // Collector revoke tests - - function testCollector_Revoke() public { - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - escrow.thawCollector(users.verifier); - skip(revokeCollectorThawingPeriod + 1); - escrow.revokeCollector(users.verifier); - vm.stopPrank(); - - (bool authorized,,) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, false); - } - - function testCollector_RevertWhen_RevokeIsNotThawing() public { - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); - vm.expectRevert(expectedError); - escrow.revokeCollector(users.verifier); - vm.stopPrank(); - } - - function testCollector_RevertWhen_RevokeIsStillThawing() public { + modifier useGateway() { vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - escrow.thawCollector(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); - vm.expectRevert(expectedError); - escrow.revokeCollector(users.verifier); + _; vm.stopPrank(); } - // Deposit tests - - function testDeposit_Tokens() public { - mint(users.gateway, 10000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - vm.stopPrank(); - - (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); - assertEq(indexerEscrowBalance, 1000 ether); - } - - function testDeposit_ManyDeposits() public { - address otherIndexer = address(0xB3); - address[] memory indexers = new address[](2); - indexers[0] = users.indexer; - indexers[1] = otherIndexer; - - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000 ether; - amounts[1] = 2000 ether; - - mint(users.gateway, 3000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 3000 ether); - escrow.depositMany(indexers, amounts); - vm.stopPrank(); - - (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); - assertEq(indexerEscrowBalance, 1000 ether); - - (uint256 otherIndexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, otherIndexer); - assertEq(otherIndexerEscrowBalance, 2000 ether); + modifier approveEscrow(uint256 amount) { + _approveEscrow(amount); + _; } - function testDeposit_RevertWhen_ManyDepositsInputsLengthMismatch() public { - address otherIndexer = address(0xB3); - address[] memory indexers = new address[](2); - indexers[0] = users.indexer; - indexers[1] = otherIndexer; - - uint256[] memory amounts = new uint256[](1); - amounts[0] = 1000 ether; - - mint(users.gateway, 1000 ether); - token.approve(address(escrow), 1000 ether); - - // revert - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInputsLengthMismatch()"); - vm.expectRevert(expectedError); - vm.prank(users.gateway); - escrow.depositMany(indexers, amounts); + modifier depositTokens(uint256 amount) { + vm.assume(amount > 0); + vm.assume(amount <= 10000 ether); + _depositTokens(amount); + _; } - // Thaw tests - - function testThaw_Tokens() public { - mint(users.gateway, 1000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - escrow.thaw(users.indexer, 100 ether); - vm.stopPrank(); - - (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.indexer); - assertEq(amountThawing, 100 ether); - assertEq(thawEndTimestamp, block.timestamp + withdrawEscrowThawingPeriod); + function setUp() public virtual override { + HorizonStakingSharedTest.setUp(); } - function testThaw_RevertWhen_InsufficientThawAmount() public { - mint(users.gateway, 1000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - - // revert - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientThawAmount()"); - vm.expectRevert(expectedError); - escrow.thaw(users.indexer, 0); - vm.stopPrank(); - } - - function testThaw_RevertWhen_InsufficientAmount() public { - mint(users.gateway, 1000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - - // revert - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", 1000 ether, 2000 ether); - vm.expectRevert(expectedError); - escrow.thaw(users.indexer, 2000 ether); - vm.stopPrank(); - } - - // Withdraw tests - - function testWithdraw_Tokens() public { - mint(users.gateway, 1000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - escrow.thaw(users.indexer, 100 ether); - - // advance time - skip(withdrawEscrowThawingPeriod + 1); - - escrow.withdraw(users.indexer); - vm.stopPrank(); - - (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); - assertEq(indexerEscrowBalance, 900 ether); - } - - function testWithdraw_RevertWhen_NotThawing() public { - mint(users.gateway, 1000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - - // revert - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); - vm.expectRevert(expectedError); - escrow.withdraw(users.indexer); - vm.stopPrank(); - } - - function testWithdraw_RevertWhen_StillThawing() public { - mint(users.gateway, 1000 ether); - vm.startPrank(users.gateway); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - escrow.thaw(users.indexer, 100 ether); - - // revert - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + withdrawEscrowThawingPeriod); - vm.expectRevert(expectedError); - escrow.withdraw(users.indexer); - vm.stopPrank(); - } - - // Collect tests - - function testCollect() public { - uint256 amount = 1000 ether; - createProvision(amount); - setDelegationFeeCut(0, 100000); - - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); - vm.stopPrank(); - - uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - vm.prank(users.verifier); - escrow.collect(users.gateway, users.indexer, subgraphDataServiceAddress, 100 ether, IGraphPayments.PaymentType.IndexingFees, 3 ether); - - uint256 indexerBalance = token.balanceOf(users.indexer); - assertEq(indexerBalance - indexerPreviousBalance, 86 ether); - } - - function testCollect_RevertWhen_CollectorNotAuthorized() public { - address indexer = address(0xA3); - uint256 amount = 1000 ether; - - vm.startPrank(users.verifier); - uint256 dataServiceCut = 30000; // 3% - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); - vm.expectRevert(expectedError); - escrow.collect(users.gateway, indexer, subgraphDataServiceAddress, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); - vm.stopPrank(); - } - - function testCollect_RevertWhen_CollectorHasInsufficientAmount() public { - vm.prank(users.gateway); - escrow.approveCollector(users.verifier, 100 ether); - - address indexer = address(0xA3); - uint256 amount = 1000 ether; - - mint(users.gateway, amount); - vm.startPrank(users.gateway); + function _depositTokens(uint256 amount) internal { token.approve(address(escrow), amount); - escrow.deposit(indexer, amount); - vm.stopPrank(); - - vm.startPrank(users.verifier); - uint256 dataServiceCut = 30 ether; - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", 100 ether, 1000 ether); - vm.expectRevert(expectedError); - escrow.collect(users.gateway, indexer, subgraphDataServiceAddress, 1000 ether, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); - vm.stopPrank(); + escrow.deposit(users.indexer, amount); } - function testCollect_RevertWhen_SenderHasInsufficientAmountInEscrow() public { - mint(users.gateway, 1000 ether); - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 100 ether); - vm.stopPrank(); - - vm.prank(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", 100 ether, 200 ether); - vm.expectRevert(expectedError); - escrow.collect(users.gateway, users.indexer, subgraphDataServiceAddress, 200 ether, IGraphPayments.PaymentType.IndexingFees, 3 ether); - vm.stopPrank(); + function _approveEscrow(uint256 amount) internal { + token.approve(address(escrow), amount); } } \ No newline at end of file diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol new file mode 100644 index 000000000..a1d7a3a5f --- /dev/null +++ b/packages/horizon/test/escrow/collect.t.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { GraphEscrowTest } from "./GraphEscrow.t.sol"; +import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; + +contract GraphEscrowCollectTest is GraphEscrowTest { + + function testCollect() public { + uint256 amount = 1000 ether; + createProvision(amount); + setDelegationFeeCut(0, 100000); + + vm.startPrank(users.gateway); + escrow.approveCollector(users.verifier, 1000 ether); + token.approve(address(escrow), 1000 ether); + escrow.deposit(users.indexer, 1000 ether); + vm.stopPrank(); + + uint256 indexerPreviousBalance = token.balanceOf(users.indexer); + vm.prank(users.verifier); + escrow.collect(users.gateway, users.indexer, subgraphDataServiceAddress, 100 ether, IGraphPayments.PaymentType.IndexingFees, 3 ether); + + uint256 indexerBalance = token.balanceOf(users.indexer); + assertEq(indexerBalance - indexerPreviousBalance, 86 ether); + } + + function testCollect_RevertWhen_CollectorNotAuthorized() public { + address indexer = address(0xA3); + uint256 amount = 1000 ether; + + vm.startPrank(users.verifier); + uint256 dataServiceCut = 30000; // 3% + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); + vm.expectRevert(expectedError); + escrow.collect(users.gateway, indexer, subgraphDataServiceAddress, amount, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + vm.stopPrank(); + } + + function testCollect_RevertWhen_CollectorHasInsufficientAmount() public { + vm.prank(users.gateway); + escrow.approveCollector(users.verifier, 100 ether); + + address indexer = address(0xA3); + uint256 amount = 1000 ether; + + vm.startPrank(users.gateway); + token.approve(address(escrow), amount); + escrow.deposit(indexer, amount); + vm.stopPrank(); + + vm.startPrank(users.verifier); + uint256 dataServiceCut = 30 ether; + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", 100 ether, 1000 ether); + vm.expectRevert(expectedError); + escrow.collect(users.gateway, indexer, subgraphDataServiceAddress, 1000 ether, IGraphPayments.PaymentType.IndexingFees, dataServiceCut); + vm.stopPrank(); + } + + function testCollect_RevertWhen_SenderHasInsufficientAmountInEscrow() public { + vm.startPrank(users.gateway); + escrow.approveCollector(users.verifier, 1000 ether); + token.approve(address(escrow), 1000 ether); + escrow.deposit(users.indexer, 100 ether); + vm.stopPrank(); + + vm.prank(users.verifier); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", 100 ether, 200 ether); + vm.expectRevert(expectedError); + escrow.collect(users.gateway, users.indexer, subgraphDataServiceAddress, 200 ether, IGraphPayments.PaymentType.IndexingFees, 3 ether); + vm.stopPrank(); + } +} \ No newline at end of file diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol new file mode 100644 index 000000000..f4ef2b11c --- /dev/null +++ b/packages/horizon/test/escrow/collector.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { GraphEscrowTest } from "./GraphEscrow.t.sol"; + +contract GraphEscrowCollectorTest is GraphEscrowTest { + function setUp() public virtual override { + GraphEscrowTest.setUp(); + vm.prank(users.gateway); + escrow.approveCollector(users.verifier, 1000 ether); + } + + // Collector approve tests + + function testCollector_Approve() public view { + (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, 0); + } + + // Collector thaw tests + + function testCollector_Thaw() public { + vm.prank(users.gateway); + escrow.thawCollector(users.verifier); + + (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + } + + // Collector cancel thaw tests + + function testCollector_CancelThaw() public { + vm.prank(users.gateway); + escrow.thawCollector(users.verifier); + + (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + + vm.prank(users.gateway); + escrow.cancelThawCollector(users.verifier); + + (authorized,, thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(authorized, true); + assertEq(thawEndTimestamp, 0); + } + + function testCollector_RevertWhen_CancelThawIsNotThawing() public { + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + vm.expectRevert(expectedError); + escrow.cancelThawCollector(users.verifier); + vm.stopPrank(); + } + + // Collector revoke tests + + function testCollector_Revoke() public { + vm.startPrank(users.gateway); + escrow.thawCollector(users.verifier); + skip(revokeCollectorThawingPeriod + 1); + escrow.revokeCollector(users.verifier); + vm.stopPrank(); + + (bool authorized,,) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(authorized, false); + } + + function testCollector_RevertWhen_RevokeIsNotThawing() public { + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + vm.expectRevert(expectedError); + vm.prank(users.gateway); + escrow.revokeCollector(users.verifier); + } + + function testCollector_RevertWhen_RevokeIsStillThawing() public { + vm.startPrank(users.gateway); + escrow.thawCollector(users.verifier); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); + vm.expectRevert(expectedError); + escrow.revokeCollector(users.verifier); + vm.stopPrank(); + } +} \ No newline at end of file diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol new file mode 100644 index 000000000..d7898bd37 --- /dev/null +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { GraphEscrowTest } from "./GraphEscrow.t.sol"; + +contract GraphEscrowDepositTest is GraphEscrowTest { + + function testDeposit_Tokens(uint256 amount) public useGateway depositTokens(amount) { + (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); + assertEq(indexerEscrowBalance, amount); + } + + function testDeposit_ManyDeposits(uint256 amount) public useGateway approveEscrow(amount) { + uint256 amountOne = amount / 2; + uint256 amountTwo = amount - amountOne; + + address otherIndexer = address(0xB3); + address[] memory indexers = new address[](2); + indexers[0] = users.indexer; + indexers[1] = otherIndexer; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = amountOne; + amounts[1] = amountTwo; + + escrow.depositMany(indexers, amounts); + + (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); + assertEq(indexerEscrowBalance, amountOne); + + (uint256 otherIndexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, otherIndexer); + assertEq(otherIndexerEscrowBalance, amountTwo); + } + + function testDeposit_RevertWhen_ManyDepositsInputsLengthMismatch( + uint256 amount + ) public useGateway approveEscrow(amount) { + address otherIndexer = address(0xB3); + address[] memory indexers = new address[](2); + indexers[0] = users.indexer; + indexers[1] = otherIndexer; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1000 ether; + + // revert + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInputsLengthMismatch()"); + vm.expectRevert(expectedError); + escrow.depositMany(indexers, amounts); + } +} \ No newline at end of file diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol new file mode 100644 index 000000000..51400feac --- /dev/null +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { GraphEscrowTest } from "./GraphEscrow.t.sol"; + +contract GraphEscrowThawTest is GraphEscrowTest { + + function testThaw_Tokens(uint256 amount) public useGateway depositTokens(amount) { + escrow.thaw(users.indexer, amount); + + (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.indexer); + assertEq(amountThawing, amount); + assertEq(thawEndTimestamp, block.timestamp + withdrawEscrowThawingPeriod); + } + + function testThaw_RevertWhen_InsufficientThawAmount( + uint256 amount + ) public useGateway depositTokens(amount) { + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientThawAmount()"); + vm.expectRevert(expectedError); + escrow.thaw(users.indexer, 0); + } + + function testThaw_RevertWhen_InsufficientAmount( + uint256 amount + ) public useGateway depositTokens(amount) { + uint256 overAmount = amount + 1; + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", amount, overAmount); + vm.expectRevert(expectedError); + escrow.thaw(users.indexer, overAmount); + } +} \ No newline at end of file diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol new file mode 100644 index 000000000..075a16a74 --- /dev/null +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { GraphEscrowTest } from "./GraphEscrow.t.sol"; + +contract GraphEscrowWithdrawTest is GraphEscrowTest { + + modifier depositAndThawTokens(uint256 amount, uint256 thawAmount) { + vm.assume(thawAmount > 0); + vm.assume(amount > thawAmount); + _depositTokens(amount); + escrow.thaw(users.indexer, thawAmount); + _; + } + + function testWithdraw_Tokens( + uint256 amount, + uint256 thawAmount + ) public useGateway depositAndThawTokens(amount, thawAmount) { + // advance time + skip(withdrawEscrowThawingPeriod + 1); + + escrow.withdraw(users.indexer); + vm.stopPrank(); + + (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); + assertEq(indexerEscrowBalance, amount - thawAmount); + } + + function testWithdraw_RevertWhen_NotThawing(uint256 amount) public useGateway depositTokens(amount) { + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + vm.expectRevert(expectedError); + escrow.withdraw(users.indexer); + vm.stopPrank(); + } + + function testWithdraw_RevertWhen_StillThawing( + uint256 amount, + uint256 thawAmount + ) public useGateway depositAndThawTokens(amount, thawAmount) { + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + withdrawEscrowThawingPeriod); + vm.expectRevert(expectedError); + escrow.withdraw(users.indexer); + vm.stopPrank(); + } +} \ No newline at end of file diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index e7889101f..afcecd803 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -5,9 +5,9 @@ import "forge-std/Test.sol"; import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; -import { HorizonStaking_Shared_Test } from "../shared/horizon-staking/HorizonStaking.t.sol"; +import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaking.t.sol"; -contract GraphPaymentsTest is HorizonStaking_Shared_Test { +contract GraphPaymentsTest is HorizonStakingSharedTest { function testCollect() public { // Setup Staking diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol index 62a8db3ac..c5aec8aa2 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol @@ -5,15 +5,13 @@ import "forge-std/Test.sol"; import { GraphBaseTest } from "../../GraphBase.t.sol"; -abstract contract HorizonStaking_Shared_Test is GraphBaseTest { +abstract contract HorizonStakingSharedTest is GraphBaseTest { /* Set Up */ - // function setUp() public virtual override { - // GraphBaseTest.setUp(); - - - // } + function setUp() public virtual override { + GraphBaseTest.setUp(); + } /* Helpers */ From 6165dc96a6b18d10af1317cc135880ff5aed403a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 20 May 2024 15:01:25 -0300 Subject: [PATCH 025/277] fix: typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/utilities/AllocationManager.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 3e43fc0fb..ae280c5a9 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -90,7 +90,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager bytes32 _subgraphDeploymentId, uint256 _tokens, bytes memory _allocationProof, - uint32 __delegationRatio + uint32 _delegationRatio ) internal returns (Allocation.State memory) { if (_allocationId == address(0)) revert AllocationManagerInvalidAllocationId(); @@ -109,7 +109,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager ); // Check that the indexer has enough tokens available - allocationProvisionTracker.lock(GRAPH_STAKING, _indexer, _tokens, delegationRatio); + allocationProvisionTracker.lock(GRAPH_STAKING, _indexer, _tokens, _delegationRatio); // Update total allocated tokens for the subgraph deployment subgraphAllocatedTokens[allocation.subgraphDeploymentId] = @@ -182,7 +182,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager function _resizeAllocation( address _allocationId, uint256 _tokens, - uint3 _ _delegationRatio + uint32 _delegationRatio ) internal returns (Allocation.State memory) { Allocation.State memory allocation = allocations.get(_allocationId); @@ -194,7 +194,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Update provision tracker uint256 oldTokens = allocation.tokens; if (_tokens > oldTokens) { - allocationProvisionTracker.lock(GRAPH_STAKING, allocation.indexer, _tokens - oldTokens, delegationRatio); + allocationProvisionTracker.lock(GRAPH_STAKING, allocation.indexer, _tokens - oldTokens, _delegationRatio); } else { allocationProvisionTracker.release(allocation.indexer, oldTokens - _tokens); } From fe747d167b841729c72b14f90c50d1d1b544a444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 20 May 2024 16:58:56 -0300 Subject: [PATCH 026/277] chore: lint horizon package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/contracts/GraphDirectory.sol | 20 +- .../horizon/contracts/escrow/GraphEscrow.sol | 50 +- .../contracts/escrow/GraphEscrowStorage.sol | 4 +- .../contracts/interfaces/IGraphToken.sol | 26 +- .../interfaces/IHorizonStakingBase.sol | 122 ++- .../interfaces/IHorizonStakingExtension.sol | 65 +- .../interfaces/IHorizonStakingTypes.sol | 5 +- .../horizon/contracts/interfaces/IManaged.sol | 4 +- .../IStakingBackwardsCompatibility.sol | 91 +-- .../contracts/mocks/ControllerMock.sol | 92 +-- .../horizon/contracts/mocks/MockGRTToken.sol | 39 +- .../contracts/payments/GraphPayments.sol | 9 +- .../payments/GraphPaymentsStorage.sol | 4 +- .../contracts/staking/HorizonStaking.sol | 710 +++++++++--------- .../staking/HorizonStakingExtension.sol | 221 +++--- .../staking/HorizonStakingStorage.sol | 45 +- .../staking/StakingBackwardsCompatibility.sol | 304 ++++---- .../contracts/staking/utilities/Managed.sol | 75 +- packages/horizon/package.json | 1 + packages/solhint-graph-config/index.js | 2 + packages/solhint-plugin-graph/index.js | 6 + yarn.lock | 1 + 22 files changed, 953 insertions(+), 943 deletions(-) diff --git a/packages/horizon/contracts/GraphDirectory.sol b/packages/horizon/contracts/GraphDirectory.sol index b509f792a..f36b0f9b3 100644 --- a/packages/horizon/contracts/GraphDirectory.sol +++ b/packages/horizon/contracts/GraphDirectory.sol @@ -24,15 +24,15 @@ contract GraphDirectory { address public immutable GRAPH_PAYMENTS; address public immutable GRAPH_ESCROW; - constructor(address _controller) { - CONTROLLER = _controller; - STAKING = IController(_controller).getContractProxy(keccak256("Staking")); - EPOCH_MANAGER = IController(_controller).getContractProxy(keccak256("EpochManager")); - GRAPH_TOKEN = IController(_controller).getContractProxy(keccak256("GraphToken")); - GRAPH_TOKEN_GATEWAY = IController(_controller).getContractProxy(keccak256("GraphTokenGateway")); - REWARDS_MANAGER = IController(_controller).getContractProxy(keccak256("RewardsManager")); - CURATION = IController(_controller).getContractProxy(keccak256("Curation")); - GRAPH_PAYMENTS = IController(_controller).getContractProxy(keccak256("GraphPayments")); - GRAPH_ESCROW = IController(_controller).getContractProxy(keccak256("GraphEscrow")); + constructor(address controller) { + CONTROLLER = controller; + STAKING = IController(controller).getContractProxy(keccak256("Staking")); + EPOCH_MANAGER = IController(controller).getContractProxy(keccak256("EpochManager")); + GRAPH_TOKEN = IController(controller).getContractProxy(keccak256("GraphToken")); + GRAPH_TOKEN_GATEWAY = IController(controller).getContractProxy(keccak256("GraphTokenGateway")); + REWARDS_MANAGER = IController(controller).getContractProxy(keccak256("RewardsManager")); + CURATION = IController(controller).getContractProxy(keccak256("Curation")); + GRAPH_PAYMENTS = IController(controller).getContractProxy(keccak256("GraphPayments")); + GRAPH_ESCROW = IController(controller).getContractProxy(keccak256("GraphEscrow")); } } diff --git a/packages/horizon/contracts/escrow/GraphEscrow.sol b/packages/horizon/contracts/escrow/GraphEscrow.sol index b1c21f54d..6e6921a82 100644 --- a/packages/horizon/contracts/escrow/GraphEscrow.sol +++ b/packages/horizon/contracts/escrow/GraphEscrow.sol @@ -9,18 +9,6 @@ import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirectory { - // -- Errors -- - - error GraphEscrowNotGraphPayments(); - error GraphEscrowInputsLengthMismatch(); - error GraphEscrowInsufficientThawAmount(); - error GraphEscrowInsufficientAmount(uint256 available, uint256 required); - error GraphEscrowNotThawing(); - error GraphEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); - error GraphEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); - error GraphEscrowCollectorNotAuthorized(address sender, address dataService); - error GraphEscrowCollectorInsufficientAmount(uint256 available, uint256 required); - // -- Events -- event AuthorizedCollector(address indexed sender, address indexed dataService); @@ -39,23 +27,35 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector event Withdraw(address indexed sender, address indexed receiver, uint256 amount); event Collect(address indexed sender, address indexed receiver, uint256 amount); + // -- Errors -- + + error GraphEscrowNotGraphPayments(); + error GraphEscrowInputsLengthMismatch(); + error GraphEscrowInsufficientThawAmount(); + error GraphEscrowInsufficientAmount(uint256 available, uint256 required); + error GraphEscrowNotThawing(); + error GraphEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); + error GraphEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); + error GraphEscrowCollectorNotAuthorized(address sender, address dataService); + error GraphEscrowCollectorInsufficientAmount(uint256 available, uint256 required); + // -- Constructor -- constructor( - address _controller, - uint256 _revokeCollectorThawingPeriod, - uint256 _withdrawEscrowThawingPeriod - ) GraphDirectory(_controller) { - if (_revokeCollectorThawingPeriod > MAX_THAWING_PERIOD) { - revert GraphEscrowThawingPeriodTooLong(_revokeCollectorThawingPeriod, MAX_THAWING_PERIOD); + address controller, + uint256 revokeCollectorThawingPeriod, + uint256 withdrawEscrowThawingPeriod + ) GraphDirectory(controller) { + if (revokeCollectorThawingPeriod > MAX_THAWING_PERIOD) { + revert GraphEscrowThawingPeriodTooLong(revokeCollectorThawingPeriod, MAX_THAWING_PERIOD); } - if (_withdrawEscrowThawingPeriod > MAX_THAWING_PERIOD) { - revert GraphEscrowThawingPeriodTooLong(_withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD); + if (withdrawEscrowThawingPeriod > MAX_THAWING_PERIOD) { + revert GraphEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD); } - revokeCollectorThawingPeriod = _revokeCollectorThawingPeriod; - withdrawEscrowThawingPeriod = _withdrawEscrowThawingPeriod; + revokeCollectorThawingPeriod = revokeCollectorThawingPeriod; + withdrawEscrowThawingPeriod = withdrawEscrowThawingPeriod; } // approve a data service to collect funds @@ -67,7 +67,9 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector // thaw a data service's collector authorization function thawCollector(address dataService) external { - authorizedCollectors[msg.sender][dataService].thawEndTimestamp = block.timestamp + revokeCollectorThawingPeriod; + authorizedCollectors[msg.sender][dataService].thawEndTimestamp = + block.timestamp + + REVOKE_COLLECTOR_THAWING_PERIOD; emit ThawCollector(msg.sender, dataService); } @@ -147,7 +149,7 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector // Set amount to thaw account.amountThawing = amount; // Set when the thaw is complete (thawing period number of seconds after current timestamp) - account.thawEndTimestamp = block.timestamp + withdrawEscrowThawingPeriod; + account.thawEndTimestamp = block.timestamp + WITHDRAW_ESCROW_THAWING_PERIOD; emit Thaw(msg.sender, receiver, amount, account.amountThawing, account.thawEndTimestamp); } diff --git a/packages/horizon/contracts/escrow/GraphEscrowStorage.sol b/packages/horizon/contracts/escrow/GraphEscrowStorage.sol index 158b7fae0..89a49e756 100644 --- a/packages/horizon/contracts/escrow/GraphEscrowStorage.sol +++ b/packages/horizon/contracts/escrow/GraphEscrowStorage.sol @@ -17,8 +17,8 @@ contract GraphEscrowStorageV1Storage { uint256 public constant MAX_THAWING_PERIOD = 90 days; // Thawing period for authorized collectors - uint256 public immutable revokeCollectorThawingPeriod; + uint256 public immutable REVOKE_COLLECTOR_THAWING_PERIOD; // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn - uint256 public immutable withdrawEscrowThawingPeriod; + uint256 public immutable WITHDRAW_ESCROW_THAWING_PERIOD; } diff --git a/packages/horizon/contracts/interfaces/IGraphToken.sol b/packages/horizon/contracts/interfaces/IGraphToken.sol index 27f68a0d2..d00e81fc1 100644 --- a/packages/horizon/contracts/interfaces/IGraphToken.sol +++ b/packages/horizon/contracts/interfaces/IGraphToken.sol @@ -9,30 +9,28 @@ interface IGraphToken is IERC20 { function burn(uint256 amount) external; - function burnFrom(address _from, uint256 amount) external; + function burnFrom(address from, uint256 amount) external; - function mint(address _to, uint256 _amount) external; + function mint(address to, uint256 amount) external; // -- Mint Admin -- - function addMinter(address _account) external; + function addMinter(address account) external; - function removeMinter(address _account) external; + function removeMinter(address account) external; function renounceMinter() external; - function isMinter(address _account) external view returns (bool); - // -- Permit -- function permit( - address _owner, - address _spender, - uint256 _value, - uint256 _deadline, - uint8 _v, - bytes32 _r, - bytes32 _s + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s ) external; // -- Allowance -- @@ -40,4 +38,6 @@ interface IGraphToken is IERC20 { function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); + + function isMinter(address account) external view returns (bool); } diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol index 1fc539f96..41f1ae1df 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol @@ -113,20 +113,20 @@ interface IHorizonStakingBase is IHorizonStakingTypes { ); // deposit stake - function stake(uint256 _tokens) external; + function stake(uint256 tokens) external; - function stakeTo(address _serviceProvider, uint256 _tokens) external; + function stakeTo(address serviceProvider, uint256 tokens) external; // can be called by anyone if the indexer has provisioned stake to this verifier - function stakeToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external; + function stakeToProvision(address serviceProvider, address verifier, uint256 tokens) external; // create a provision function provision( - address _serviceProvider, - address _verifier, - uint256 _tokens, - uint32 _maxVerifierCut, - uint64 _thawingPeriod + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod ) external; /** @@ -135,65 +135,56 @@ interface IHorizonStakingBase is IHorizonStakingTypes { * service, where the data service is the verifier. Only authorized verifiers can be used. * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) - * @param _tokens The amount of tokens that will be locked and slashable - * @param _maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing - * @param _thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param tokens The amount of tokens that will be locked and slashable + * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ function provisionLocked( - address _serviceProvider, - address _verifier, - uint256 _tokens, - uint32 _maxVerifierCut, - uint64 _thawingPeriod + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod ) external; // initiate a thawing to remove tokens from a provision - function thaw(address _serviceProvider, address _verifier, uint256 _tokens) external returns (bytes32); + function thaw(address serviceProvider, address verifier, uint256 tokens) external returns (bytes32); // add more tokens from idle stake to an existing provision - function addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external; + function addToProvision(address serviceProvider, address verifier, uint256 tokens) external; // moves thawed stake from a provision back into the provider's available stake - function deprovision(address _serviceProvider, address _verifier, uint256 _tokens) external; + function deprovision(address serviceProvider, address verifier, uint256 tokens) external; // moves thawed stake from one provision into another provision - function reprovision( - address _serviceProvider, - address _oldVerifier, - address _newVerifier, - uint256 _tokens - ) external; + function reprovision(address serviceProvider, address oldVerifier, address newVerifier, uint256 tokens) external; // moves thawed stake back to the owner's account - stake is removed from the protocol - function unstake(uint256 _tokens) external; + function unstake(uint256 tokens) external; // delegate tokens to a provider on a data service - function delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) external; + function delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) external; // undelegate (thaw) delegated tokens from a provision - function undelegate(address _serviceProvider, address _verifier, uint256 _shares) external; + function undelegate(address serviceProvider, address verifier, uint256 shares) external; // withdraw delegated tokens after thawing function withdrawDelegated( - address _serviceProvider, - address _verifier, - address _newServiceProvider, - uint256 _minSharesForNewProvider + address serviceProvider, + address verifier, + address newServiceProvider, + uint256 minSharesForNewProvider ) external; function slash( - address _serviceProvider, - uint256 _tokens, - uint256 _verifierCutAmount, - address _verifierCutDestination + address serviceProvider, + uint256 tokens, + uint256 verifierCutAmount, + address verifierCutDestination ) external; - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address _serviceProvider) external view returns (uint256 tokens); - /** * @notice Withdraw indexer tokens once the thawing period has passed. * @dev This is only needed during the transition period while we still have @@ -201,36 +192,41 @@ interface IHorizonStakingBase is IHorizonStakingTypes { */ function withdraw() external; - function setDelegationSlashingEnabled(bool _enabled) external; + function setDelegationSlashingEnabled(bool enabled) external; - /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param _operator The address to check for auth - * @param _serviceProvider The service provider on behalf of whom they're claiming to act - * @param _verifier The verifier / data service on which they're claiming to act - */ - function isAuthorized(address _operator, address _serviceProvider, address _verifier) external view returns (bool); - - function getProviderTokensAvailable(address _serviceProvider, address _verifier) external view returns (uint256); - function setMaxThawingPeriod(uint64 _maxThawingPeriod) external; + function setMaxThawingPeriod(uint64 maxThawingPeriod) external; - function setAllowedLockedVerifier(address _verifier, bool _allowed) external; + function setAllowedLockedVerifier(address verifier, bool allowed) external; /** * @notice Add tokens to a delegation pool (without getting shares). * Used by data services to pay delegation fees/rewards. - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned - * @param _tokens The amount of tokens to add to the delegation pool + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to add to the delegation pool */ - function addToDelegationPool(address _serviceProvider, address _verifier, uint256 _tokens) external; + function addToDelegationPool(address serviceProvider, address verifier, uint256 tokens) external; function setProvisionParameters( - address _serviceProvider, - address _verifier, - uint32 _maxVerifierCut, - uint64 _thawingPeriod + address serviceProvider, + address verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod ) external; - function acceptProvisionParameters(address _serviceProvider) external; + function acceptProvisionParameters(address serviceProvider) external; + + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address serviceProvider) external view returns (uint256 tokens); + + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param operator The address to check for auth + * @param serviceProvider The service provider on behalf of whom they're claiming to act + * @param verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); + + function getProviderTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); } diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol index 546f9fefa..7c5da23e2 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol @@ -18,57 +18,56 @@ interface IHorizonStakingExtension { uint256 feeCut ); + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @param operator Address to authorize or unauthorize + * @param verifier The verifier / data service on which they'll be allowed to operate + * @param allowed Whether the operator is authorized or not + */ + function setOperator(address operator, address verifier, bool allowed) external; + + // for vesting contracts + function setOperatorLocked(address operator, address verifier, bool allowed) external; + + function setDelegationFeeCut(address serviceProvider, address verifier, uint256 feeType, uint256 feeCut) external; + function getStake(address serviceProvider) external view returns (uint256); - function getDelegatedTokensAvailable(address _serviceProvider, address _verifier) external view returns (uint256); + function getDelegatedTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); + function getTokensAvailable( - address _serviceProvider, - address _verifier, - uint32 _delegationRatio + address serviceProvider, + address verifier, + uint32 delegationRatio ) external view returns (uint256); function getServiceProvider( address serviceProvider ) external view returns (IHorizonStakingTypes.ServiceProvider memory); - /** - * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. - * @param _operator Address to authorize or unauthorize - * @param _verifier The verifier / data service on which they'll be allowed to operate - * @param _allowed Whether the operator is authorized or not - */ - function setOperator(address _operator, address _verifier, bool _allowed) external; - - // for vesting contracts - function setOperatorLocked(address _operator, address _verifier, bool _allowed) external; - function getMaxThawingPeriod() external view returns (uint64); function getDelegationPool( - address _serviceProvider, - address _verifier + address serviceProvider, + address verifier ) external view returns (IHorizonStakingTypes.DelegationPool memory); + function getDelegation( - address _delegator, - address _serviceProvider, - address _verifier + address delegator, + address serviceProvider, + address verifier ) external view returns (IHorizonStakingTypes.Delegation memory); - function getThawRequest(bytes32 _thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory); + + function getThawRequest(bytes32 thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory); + function getProvision( - address _serviceProvider, - address _verifier + address serviceProvider, + address verifier ) external view returns (IHorizonStakingTypes.Provision memory); - function setDelegationFeeCut( - address _serviceProvider, - address _verifier, - uint256 _feeType, - uint256 _feeCut - ) external; - function getDelegationFeeCut( - address _serviceProvider, - address _verifier, - uint256 _feeType + address serviceProvider, + address verifier, + uint256 feeType ) external view returns (uint256); } diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol index f58a004b7..f737d52ee 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol @@ -3,6 +3,9 @@ pragma solidity >=0.6.12 <0.9.0; pragma abicoder v2; +// TODO: create custom var-name-mixedcase +/* solhint-disable var-name-mixedcase */ + interface IHorizonStakingTypes { struct Provision { // service provider tokens in the provision @@ -77,7 +80,7 @@ interface IHorizonStakingTypes { // Tokens on the Service Provider stake (staked by the provider) uint256 tokensStaked; // Tokens used in allocations - uint256 __DEPRECATED_tokensAllocated; + uint256 __DEPRECATED_tokensAllocated; // solhint-disable-line graph/leading-underscore // Tokens locked for withdrawal subject to thawing period uint256 __DEPRECATED_tokensLocked; // Block when locked tokens can be withdrawn diff --git a/packages/horizon/contracts/interfaces/IManaged.sol b/packages/horizon/contracts/interfaces/IManaged.sol index 5aa086ba7..13c129b2f 100644 --- a/packages/horizon/contracts/interfaces/IManaged.sol +++ b/packages/horizon/contracts/interfaces/IManaged.sol @@ -13,9 +13,9 @@ interface IManaged { /** * @notice (Deprecated) Set the controller that manages this contract * @dev Only the current controller can set a new controller - * @param _controller Address of the new controller + * @param controller Address of the new controller */ - function setController(address _controller) external; + function setController(address controller) external; /** * @notice Get the Controller that manages this contract diff --git a/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol b/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol index 43c93662a..088ee3776 100644 --- a/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol @@ -12,14 +12,6 @@ pragma abicoder v2; * that includes the full functionality. */ interface IStakingBackwardsCompatibility { - /** - * @dev Emitted when `delegator` delegated `tokens` to the `serviceProvider`, the delegator - * gets `shares` for the delegation pool proportionally to the tokens staked. - * This event is here for backwards compatibility, the tokens are delegated - * on the subgraph data service provision. - */ - event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); - /** * @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() @@ -31,10 +23,32 @@ interface IStakingBackwardsCompatibility { uint256 createdAtEpoch; // Epoch when it was created uint256 closedAtEpoch; // Epoch when it was closed uint256 collectedFees; // Collected fees for the allocation - uint256 __DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase + uint256 DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc uint256 distributedRebates; // Collected rebates that have been rebated } + + /** + * @dev Possible states an allocation can be. + * States: + * - Null = indexer == address(0) + * - Active = not Null && tokens > 0 + * - Closed = Active && closedAtEpoch != 0 + */ + enum AllocationState { + Null, + Active, + Closed + } + + /** + * @dev Emitted when `delegator` delegated `tokens` to the `serviceProvider`, the delegator + * gets `shares` for the delegation pool proportionally to the tokens staked. + * This event is here for backwards compatibility, the tokens are delegated + * on the subgraph data service provision. + */ + event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); + /** * @dev Emitted when `serviceProvider` stakes `tokens` amount. */ @@ -95,35 +109,22 @@ interface IStakingBackwardsCompatibility { */ event SetOperator(address indexed indexer, address indexed operator, bool allowed); - /** - * @dev Possible states an allocation can be. - * States: - * - Null = indexer == address(0) - * - Active = not Null && tokens > 0 - * - Closed = Active && closedAtEpoch != 0 - */ - enum AllocationState { - Null, - Active, - Closed - } - /** * @notice 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. + * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. */ - function setCounterpartStakingAddress(address _counterpart) external; + function setCounterpartStakingAddress(address counterpart) external; /** * @notice Close an allocation and free the staked tokens. * To be eligible for rewards a proof of indexing must be presented. * Presenting a bad proof is subject to slashable condition. * To opt out of rewards set _poi to 0x0 - * @param _allocationID The allocation identifier - * @param _poi Proof of indexing submitted for the allocated period + * @param allocationID The allocation identifier + * @param poi Proof of indexing submitted for the allocated period */ - function closeAllocation(address _allocationID, bytes32 _poi) external; + function closeAllocation(address allocationID, bytes32 poi) external; /** * @notice Collect query fees from state channels and assign them to an allocation. @@ -132,58 +133,58 @@ interface IStakingBackwardsCompatibility { * 1) Accept calls with zero tokens. * 2) Accept calls after an allocation passed the dispute period, in that case, all * the received tokens are burned. - * @param _tokens Amount of tokens to collect - * @param _allocationID Allocation where the tokens will be assigned + * @param tokens Amount of tokens to collect + * @param allocationID Allocation where the tokens will be assigned */ - function collect(uint256 _tokens, address _allocationID) external; + function collect(uint256 tokens, address allocationID) external; /** * @notice Return true if operator is allowed for indexer. - * @param _operator Address of the operator - * @param _indexer Address of the indexer + * @param operator Address of the operator + * @param indexer Address of the indexer * @return True if operator is allowed for indexer, false otherwise */ - function isOperator(address _operator, address _indexer) external view returns (bool); + function isOperator(address operator, address indexer) external view returns (bool); /** * @notice Getter that returns if an indexer has any stake. - * @param _indexer Address of the indexer + * @param indexer Address of the indexer * @return True if indexer has staked tokens */ - function hasStake(address _indexer) external view returns (bool); + function hasStake(address indexer) external view returns (bool); /** * @notice Get the total amount of tokens staked by the indexer. - * @param _indexer Address of the indexer + * @param indexer Address of the indexer * @return Amount of tokens staked by the indexer */ - function getIndexerStakedTokens(address _indexer) external view returns (uint256); + function getIndexerStakedTokens(address indexer) external view returns (uint256); /** * @notice Return the allocation by ID. - * @param _allocationID Address used as allocation identifier + * @param allocationID Address used as allocation identifier * @return Allocation data */ - function getAllocation(address _allocationID) external view returns (Allocation memory); + function getAllocation(address allocationID) external view returns (Allocation memory); /** * @notice Return the current state of an allocation - * @param _allocationID Allocation identifier + * @param allocationID Allocation identifier * @return AllocationState enum with the state of the allocation */ - function getAllocationState(address _allocationID) external view returns (AllocationState); + function getAllocationState(address allocationID) external view returns (AllocationState); /** * @notice Return if allocationID is used. - * @param _allocationID Address used as signer by the indexer for an allocation + * @param allocationID Address used as signer by the indexer for an allocation * @return True if allocationID already used */ - function isAllocation(address _allocationID) external view returns (bool); + function isAllocation(address allocationID) external view returns (bool); /** * @notice Return the total amount of tokens allocated to subgraph. - * @param _subgraphDeploymentID Deployment ID for the subgraph + * @param subgraphDeploymentID Deployment ID for the subgraph * @return Total tokens allocated to subgraph */ - function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view returns (uint256); + function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view returns (uint256); } diff --git a/packages/horizon/contracts/mocks/ControllerMock.sol b/packages/horizon/contracts/mocks/ControllerMock.sol index f8c976cf9..a30993a89 100644 --- a/packages/horizon/contracts/mocks/ControllerMock.sol +++ b/packages/horizon/contracts/mocks/ControllerMock.sol @@ -12,7 +12,7 @@ import { IManaged } from "@graphprotocol/contracts/contracts/governance/IManaged */ contract ControllerMock is IController { /// @dev Track contract ids to contract proxy address - mapping(bytes32 => address) private _registry; + mapping(bytes32 contractName => address contractAddress) private _registry; address public governor; bool internal _paused; bool internal _partialPaused; @@ -23,59 +23,42 @@ contract ControllerMock is IController { /** * Constructor for the Controller mock - * @param _governor Address of the governor + * @param governor_ Address of the governor */ - constructor(address _governor) { - governor = _governor; - } - - /** - * @notice Getter to access governor - * @return Address of the governor - */ - function getGovernor() external view override returns (address) { - return governor; + constructor(address governor_) { + governor = governor_; } // -- Registry -- /** * @notice Register contract id and mapped address - * @param _id Contract id (keccak256 hash of contract name) - * @param _contractAddress Contract address + * @param id Contract id (keccak256 hash of contract name) + * @param contractAddress Contract address */ - function setContractProxy(bytes32 _id, address _contractAddress) external override { - require(_contractAddress != address(0), "Contract address must be set"); - _registry[_id] = _contractAddress; - emit SetContractProxy(_id, _contractAddress); + function setContractProxy(bytes32 id, address contractAddress) external override { + require(contractAddress != address(0), "Contract address must be set"); + _registry[id] = contractAddress; + emit SetContractProxy(id, contractAddress); } /** * @notice Unregister a contract address - * @param _id Contract id (keccak256 hash of contract name) - */ - function unsetContractProxy(bytes32 _id) external override { - _registry[_id] = address(0); - emit SetContractProxy(_id, address(0)); - } - - /** - * @notice Get contract proxy address by its id - * @param _id Contract id (keccak256 hash of contract name) - * @return Address of the proxy contract for the provided id + * @param id Contract id (keccak256 hash of contract name) */ - function getContractProxy(bytes32 _id) external view override returns (address) { - return _registry[_id]; + function unsetContractProxy(bytes32 id) external override { + _registry[id] = address(0); + emit SetContractProxy(id, address(0)); } /** * @notice Update a contract's controller - * @param _id Contract id (keccak256 hash of contract name) - * @param _controller New Controller address + * @param id Contract id (keccak256 hash of contract name) + * @param controller New Controller address */ - function updateController(bytes32 _id, address _controller) external override { - require(_controller != address(0), "Controller must be set"); - return IManaged(_registry[_id]).setController(_controller); + function updateController(bytes32 id, address controller) external override { + require(controller != address(0), "Controller must be set"); + return IManaged(_registry[id]).setController(controller); } // -- Pausing -- @@ -83,28 +66,45 @@ contract ControllerMock is IController { /** * @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 + * @param toPause True if the contracts should be (partially) paused, false otherwise */ - function setPartialPaused(bool _toPause) external override { - _partialPaused = _toPause; + function setPartialPaused(bool toPause) external override { + _partialPaused = 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 + * @param toPause True if the contracts should be paused, false otherwise */ - function setPaused(bool _toPause) external override { - _paused = _toPause; + function setPaused(bool toPause) external override { + _paused = toPause; } /** * @notice Change the Pause Guardian - * @param _newPauseGuardian The address of the new Pause Guardian + * @param newPauseGuardian The address of the new Pause Guardian + */ + function setPauseGuardian(address newPauseGuardian) external override { + require(newPauseGuardian != address(0), "PauseGuardian must be set"); + _pauseGuardian = newPauseGuardian; + } + + /** + * @notice Getter to access governor + * @return Address of the governor + */ + function getGovernor() external view override returns (address) { + return governor; + } + + /** + * @notice Get contract proxy address by its id + * @param id Contract id (keccak256 hash of contract name) + * @return Address of the proxy contract for the provided id */ - function setPauseGuardian(address _newPauseGuardian) external override { - require(_newPauseGuardian != address(0), "PauseGuardian must be set"); - _pauseGuardian = _newPauseGuardian; + function getContractProxy(bytes32 id) external view override returns (address) { + return _registry[id]; } /** diff --git a/packages/horizon/contracts/mocks/MockGRTToken.sol b/packages/horizon/contracts/mocks/MockGRTToken.sol index a39faaed3..1212f3e70 100644 --- a/packages/horizon/contracts/mocks/MockGRTToken.sol +++ b/packages/horizon/contracts/mocks/MockGRTToken.sol @@ -1,46 +1,47 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; contract MockGRTToken is ERC20, IGraphToken { constructor() ERC20("Graph Token", "GRT") {} function burn(uint256 amount) external {} - function burnFrom(address _from, uint256 amount) external { - _burn(_from, amount); - } - - function mint(address to, uint256 amount) public { - _mint(to, amount); + function burnFrom(address from, uint256 amount) external { + _burn(from, amount); } // -- Mint Admin -- - function addMinter(address _account) external {} + function addMinter(address account) external {} - function removeMinter(address _account) external {} + function removeMinter(address account) external {} function renounceMinter() external {} - function isMinter(address _account) external view returns (bool) {} - // -- Permit -- function permit( - address _owner, - address _spender, - uint256 _value, - uint256 _deadline, - uint8 _v, - bytes32 _r, - bytes32 _s + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s ) external {} // -- Allowance -- function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {} + function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {} + + function isMinter(address account) external view returns (bool) {} + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 2a2fa96ba..41ba9f063 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -9,6 +9,7 @@ import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { + uint256 private immutable MAX_PPM = 1000000; // 100% in parts per million // -- Errors -- error GraphPaymentsNotThawing(); @@ -22,12 +23,10 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi // -- Parameters -- - uint256 private immutable MAX_PPM = 1000000; // 100% in parts per million - // -- Constructor -- - constructor(address _controller, uint256 _protocolPaymentCut) GraphDirectory(_controller) { - protocolPaymentCut = _protocolPaymentCut; + constructor(address controller, uint256 protocolPaymentCut) GraphDirectory(controller) { + protocolPaymentCut = protocolPaymentCut; } // collect funds from a sender, pay cuts and forward the rest to the receiver @@ -43,7 +42,7 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi TokenUtils.pullTokens(graphToken, msg.sender, amount); // Pay protocol cut - uint256 tokensProtocol = (amount * protocolPaymentCut) / MAX_PPM; + uint256 tokensProtocol = (amount * PROTOCOL_PAYMENT_CUT) / MAX_PPM; TokenUtils.burnTokens(graphToken, tokensProtocol); // Pay data service cut diff --git a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol index 7d4c1c338..09a8691d8 100644 --- a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol +++ b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; - contract GraphPaymentsStorageV1Storage { // The graph protocol payment cut - uint256 public immutable protocolPaymentCut; + uint256 public immutable PROTOCOL_PAYMENT_CUT; } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 883e1f611..a773d8dd0 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -58,20 +58,20 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); error HorizonStakingSlippageProtection(uint256 minExpectedAmount, uint256 actualAmount); - modifier onlyAuthorized(address _serviceProvider, address _verifier) { - if (!isAuthorized(msg.sender, _serviceProvider, _verifier)) { - revert HorizonStakingNotAuthorized(msg.sender, _serviceProvider, _verifier); + modifier onlyAuthorized(address serviceProvider, address verifier) { + if (!isAuthorized(msg.sender, serviceProvider, verifier)) { + revert HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier); } _; } constructor( - address _controller, - address _stakingExtensionAddress, - address _subgraphDataServiceAddress - ) Managed(_controller) { - STAKING_EXTENSION_ADDRESS = _stakingExtensionAddress; - SUBGRAPH_DATA_SERVICE_ADDRESS = _subgraphDataServiceAddress; + address controller, + address stakingExtensionAddress, + address subgraphDataServiceAddress + ) Managed(controller) { + STAKING_EXTENSION_ADDRESS = stakingExtensionAddress; + SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; } /** @@ -111,63 +111,46 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp /** * @notice Deposit tokens on the caller's stake. - * @param _tokens Amount of tokens to stake + * @param tokens Amount of tokens to stake */ - function stake(uint256 _tokens) external override { - stakeTo(msg.sender, _tokens); - } - - /** - * @notice Deposit tokens on the service provider stake, on behalf of the service provider. - * @param _serviceProvider Address of the indexer - * @param _tokens Amount of tokens to stake - */ - function stakeTo(address _serviceProvider, uint256 _tokens) public override notPartialPaused { - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - - // Transfer tokens to stake from caller to this contract - TokenUtils.pullTokens(_graphToken(), msg.sender, _tokens); - - // Stake the transferred tokens - _stake(_serviceProvider, _tokens); + function stake(uint256 tokens) external override { + stakeTo(msg.sender, tokens); } function setProvisionParameters( - address _serviceProvider, - address _verifier, - uint32 _maxVerifierCut, - uint64 _thawingPeriod - ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { - Provision storage prov = provisions[_serviceProvider][_verifier]; - prov.maxVerifierCutPending = _maxVerifierCut; - prov.thawingPeriodPending = _thawingPeriod; - emit ProvisionParametersStaged(_serviceProvider, _verifier, _maxVerifierCut, _thawingPeriod); - } - - function acceptProvisionParameters(address _serviceProvider) external override notPartialPaused { + address serviceProvider, + address verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + Provision storage prov = _provisions[serviceProvider][verifier]; + prov.maxVerifierCutPending = maxVerifierCut; + prov.thawingPeriodPending = thawingPeriod; + emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); + } + + function acceptProvisionParameters(address serviceProvider) external override notPartialPaused { address verifier = msg.sender; - Provision storage prov = provisions[_serviceProvider][verifier]; + Provision storage prov = _provisions[serviceProvider][verifier]; prov.maxVerifierCut = prov.maxVerifierCutPending; prov.thawingPeriod = prov.thawingPeriodPending; - emit ProvisionParametersSet(_serviceProvider, verifier, prov.maxVerifierCut, prov.thawingPeriod); + emit ProvisionParametersSet(serviceProvider, verifier, prov.maxVerifierCut, prov.thawingPeriod); } /** * @notice Deposit tokens on the service provider stake, on behalf of the service provider, provisioned * to a specific verifier. The provider must have previously provisioned stake to that verifier. - * @param _serviceProvider Address of the indexer - * @param _verifier Address of the verifier - * @param _tokens Amount of tokens to stake + * @param serviceProvider Address of the indexer + * @param verifier Address of the verifier + * @param tokens Amount of tokens to stake */ function stakeToProvision( - address _serviceProvider, - address _verifier, - uint256 _tokens + address serviceProvider, + address verifier, + uint256 tokens ) external override notPartialPaused { - stakeTo(_serviceProvider, _tokens); - _addToProvision(_serviceProvider, _verifier, _tokens); + stakeTo(serviceProvider, tokens); + _addToProvision(serviceProvider, verifier, tokens); } /** @@ -176,24 +159,24 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp * service, where the data service is the verifier. * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) - * @param _tokens The amount of tokens that will be locked and slashable - * @param _maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing - * @param _thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param tokens The amount of tokens that will be locked and slashable + * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ function provision( - address _serviceProvider, - address _verifier, - uint256 _tokens, - uint32 _maxVerifierCut, - uint64 _thawingPeriod - ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { - if (getIdleStake(_serviceProvider) < _tokens) { + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + if (getIdleStake(serviceProvider) < tokens) { revert HorizonStakingInsufficientCapacity(); } - _createProvision(_serviceProvider, _tokens, _verifier, _maxVerifierCut, _thawingPeriod); + _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } /** @@ -202,75 +185,73 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp * service, where the data service is the verifier. Only authorized verifiers can be used. * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) - * @param _tokens The amount of tokens that will be locked and slashable - * @param _maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing - * @param _thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param tokens The amount of tokens that will be locked and slashable + * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ function provisionLocked( - address _serviceProvider, - address _verifier, - uint256 _tokens, - uint32 _maxVerifierCut, - uint64 _thawingPeriod - ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { - if (getIdleStake(_serviceProvider) < _tokens) { + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + if (getIdleStake(serviceProvider) < tokens) { revert HorizonStakingInsufficientCapacity(); } - if (!allowedLockedVerifiers[_verifier]) { - revert HorizonStakingInvalidVerifier(_verifier); + if (!_allowedLockedVerifiers[verifier]) { + revert HorizonStakingInvalidVerifier(verifier); } - _createProvision(_serviceProvider, _tokens, _verifier, _maxVerifierCut, _thawingPeriod); + _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } /** * @notice Add more tokens to an existing provision. * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned - * @param _tokens The amount of tokens to add to the provision + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to add to the provision */ function addToProvision( - address _serviceProvider, - address _verifier, - uint256 _tokens - ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) { - _addToProvision(_serviceProvider, _verifier, _tokens); + address serviceProvider, + address verifier, + uint256 tokens + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + _addToProvision(serviceProvider, verifier, tokens); } /** * @notice Start thawing tokens to remove them from a provision. * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned - * @param _tokens The amount of tokens to thaw + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to thaw */ function thaw( - address _serviceProvider, - address _verifier, - uint256 _tokens - ) external override notPartialPaused onlyAuthorized(_serviceProvider, _verifier) returns (bytes32) { - if (_tokens == 0) { + address serviceProvider, + address verifier, + uint256 tokens + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) returns (bytes32) { + if (tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } - Provision storage prov = provisions[_serviceProvider][_verifier]; - ServiceProviderInternal storage serviceProvider = serviceProviders[_serviceProvider]; - bytes32 thawRequestId = keccak256( - abi.encodePacked(_serviceProvider, _verifier, serviceProvider.nextThawRequestNonce) - ); - serviceProvider.nextThawRequestNonce += 1; - ThawRequest storage thawRequest = thawRequests[thawRequestId]; + Provision storage prov = _provisions[serviceProvider][verifier]; + ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; + bytes32 thawRequestId = keccak256(abi.encodePacked(serviceProvider, verifier, sp.nextThawRequestNonce)); + sp.nextThawRequestNonce += 1; + ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - require(getProviderTokensAvailable(_serviceProvider, _verifier) >= _tokens, "insufficient tokens available"); - prov.tokensThawing = prov.tokensThawing + _tokens; + require(getProviderTokensAvailable(serviceProvider, verifier) >= tokens, "insufficient tokens available"); + prov.tokensThawing = prov.tokensThawing + tokens; if (prov.sharesThawing == 0) { - thawRequest.shares = _tokens; + thawRequest.shares = tokens; } else { - thawRequest.shares = (prov.sharesThawing * _tokens) / prov.tokensThawing; + thawRequest.shares = (prov.sharesThawing * tokens) / prov.tokensThawing; } thawRequest.thawingUntil = uint64(block.timestamp + uint256(prov.thawingPeriod)); @@ -282,51 +263,23 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp if (prov.nThawRequests == 0) { prov.firstThawRequestId = thawRequestId; } else { - thawRequests[prov.lastThawRequestId].next = thawRequestId; + _thawRequests[prov.lastThawRequestId].next = thawRequestId; } prov.lastThawRequestId = thawRequestId; prov.nThawRequests += 1; - emit ProvisionThawInitiated(_serviceProvider, _verifier, _tokens, thawRequest.thawingUntil, thawRequestId); + emit ProvisionThawInitiated(serviceProvider, verifier, tokens, thawRequest.thawingUntil, thawRequestId); return thawRequestId; } - /** - * @notice Get the amount of service provider's tokens in a provision that have finished thawing - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned - */ - function getThawedTokens(address _serviceProvider, address _verifier) external view returns (uint256) { - Provision storage prov = provisions[_serviceProvider][_verifier]; - if (prov.nThawRequests == 0) { - return 0; - } - bytes32 thawRequestId = prov.firstThawRequestId; - uint256 tokens = 0; - while (thawRequestId != bytes32(0)) { - ThawRequest storage thawRequest = thawRequests[thawRequestId]; - if (thawRequest.thawingUntil <= block.timestamp) { - tokens += (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; - } else { - break; - } - thawRequestId = thawRequest.next; - } - return tokens; - } - // moves thawed stake from a provision back into the provider's available stake - function deprovision( - address _serviceProvider, - address _verifier, - uint256 _tokens - ) external override notPartialPaused { - require(isAuthorized(msg.sender, _serviceProvider, _verifier), "!auth"); - if (_tokens == 0) { + function deprovision(address serviceProvider, address verifier, uint256 tokens) external override notPartialPaused { + require(isAuthorized(msg.sender, serviceProvider, verifier), "!auth"); + if (tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } - _fulfillThawRequests(_serviceProvider, _verifier, _tokens); + _fulfillThawRequests(serviceProvider, verifier, tokens); } /** @@ -334,49 +287,49 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp * This function can be called by the service provider or by an operator authorized by the provider * for the two corresponding verifiers. * The provider must have previously provisioned tokens to the new verifier. - * @param _serviceProvider The service provider address - * @param _oldVerifier The verifier address for which the tokens are currently provisioned - * @param _newVerifier The verifier address for which the tokens will be provisioned - * @param _tokens The amount of tokens to move + * @param serviceProvider The service provider address + * @param oldVerifier The verifier address for which the tokens are currently provisioned + * @param newVerifier The verifier address for which the tokens will be provisioned + * @param tokens The amount of tokens to move */ function reprovision( - address _serviceProvider, - address _oldVerifier, - address _newVerifier, - uint256 _tokens + address serviceProvider, + address oldVerifier, + address newVerifier, + uint256 tokens ) external override notPartialPaused - onlyAuthorized(_serviceProvider, _oldVerifier) - onlyAuthorized(_serviceProvider, _newVerifier) + onlyAuthorized(serviceProvider, oldVerifier) + onlyAuthorized(serviceProvider, newVerifier) { - _fulfillThawRequests(_serviceProvider, _oldVerifier, _tokens); - _addToProvision(_serviceProvider, _newVerifier, _tokens); + _fulfillThawRequests(serviceProvider, oldVerifier, tokens); + _addToProvision(serviceProvider, newVerifier, tokens); } /** * @notice Move idle stake back to the owner's account. * If tokens were thawing they must be deprovisioned first. * Stake is removed from the protocol. - * @param _tokens Amount of tokens to unstake + * @param tokens Amount of tokens to unstake */ - function unstake(uint256 _tokens) external override notPaused { + function unstake(uint256 tokens) external override notPaused { address serviceProvider = msg.sender; - if (_tokens == 0) { + if (tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } - if (getIdleStake(serviceProvider) < _tokens) { + if (getIdleStake(serviceProvider) < tokens) { revert HorizonStakingInsufficientCapacity(); } - ServiceProviderInternal storage sp = serviceProviders[serviceProvider]; + ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; uint256 stakedTokens = sp.tokensStaked; // Check that the indexer's stake minus the tokens to unstake is sufficient // to cover existing allocations // TODO this is only needed until legacy allocations are closed, // so we should remove it after the transition period - if ((stakedTokens - _tokens) < sp.__DEPRECATED_tokensAllocated) { + if ((stakedTokens - tokens) < sp.__DEPRECATED_tokensAllocated) { revert HorizonStakingInsufficientCapacityForLegacyAllocations(); } @@ -386,9 +339,9 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp // and set the thawing period to 0. uint256 lockingPeriod = __DEPRECATED_thawingPeriod; if (lockingPeriod == 0) { - sp.tokensStaked = stakedTokens - _tokens; - TokenUtils.pushTokens(_graphToken(), serviceProvider, _tokens); - emit StakeWithdrawn(serviceProvider, _tokens); + sp.tokensStaked = stakedTokens - tokens; + TokenUtils.pushTokens(_graphToken(), serviceProvider, tokens); + emit StakeWithdrawn(serviceProvider, tokens); } else { // Before locking more tokens, withdraw any unlocked ones if possible if (sp.__DEPRECATED_tokensLockedUntil != 0 && block.number >= sp.__DEPRECATED_tokensLockedUntil) { @@ -401,12 +354,12 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp MathUtils.diffOrZero(sp.__DEPRECATED_tokensLockedUntil, block.number), // Remaining thawing period sp.__DEPRECATED_tokensLocked, // Weighted by remaining unstaked tokens lockingPeriod, // Thawing period - _tokens // Weighted by new tokens to unstake + tokens // Weighted by new tokens to unstake ); } // Update balances - sp.__DEPRECATED_tokensLocked = sp.__DEPRECATED_tokensLocked + _tokens; + sp.__DEPRECATED_tokensLocked = sp.__DEPRECATED_tokensLocked + tokens; sp.__DEPRECATED_tokensLockedUntil = block.number + lockingPeriod; emit StakeLocked(serviceProvider, sp.__DEPRECATED_tokensLocked, sp.__DEPRECATED_tokensLockedUntil); } @@ -417,54 +370,54 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp * the provider has provisioned stake, and up to the amount of tokens they have provisioned. * @dev If delegation slashing is disabled, and the amount of tokens is more than the * provider's provisioned self-stake, the delegation slashing is skipped without reverting. - * @param _serviceProvider The service provider to slash - * @param _tokens The amount of tokens to slash - * @param _verifierCutAmount The amount of tokens to transfer instead of burning - * @param _verifierCutDestination The address to transfer the verifier cut to + * @param serviceProvider The service provider to slash + * @param tokens The amount of tokens to slash + * @param verifierCutAmount The amount of tokens to transfer instead of burning + * @param verifierCutDestination The address to transfer the verifier cut to */ function slash( - address _serviceProvider, - uint256 _tokens, - uint256 _verifierCutAmount, - address _verifierCutDestination + address serviceProvider, + uint256 tokens, + uint256 verifierCutAmount, + address verifierCutDestination ) external override notPartialPaused { address verifier = msg.sender; - Provision storage prov = provisions[_serviceProvider][verifier]; - if (prov.tokens < _tokens) { - revert HorizonStakingInsufficientTokens(_tokens, prov.tokens); + Provision storage prov = _provisions[serviceProvider][verifier]; + if (prov.tokens < tokens) { + revert HorizonStakingInsufficientTokens(tokens, prov.tokens); } - uint256 tokensToSlash = _tokens; + uint256 tokensToSlash = tokens; uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); if (providerTokensSlashed > 0) { - require((prov.tokens * prov.maxVerifierCut) / MAX_PPM >= _verifierCutAmount, "verifier cut too high"); - if (_verifierCutAmount > 0) { - TokenUtils.pushTokens(_graphToken(), _verifierCutDestination, _verifierCutAmount); - emit VerifierCutSent(_serviceProvider, verifier, _verifierCutDestination, _verifierCutAmount); + require((prov.tokens * prov.maxVerifierCut) / MAX_PPM >= verifierCutAmount, "verifier cut too high"); + if (verifierCutAmount > 0) { + TokenUtils.pushTokens(_graphToken(), verifierCutDestination, verifierCutAmount); + emit VerifierCutSent(serviceProvider, verifier, verifierCutDestination, verifierCutAmount); } - TokenUtils.burnTokens(_graphToken(), providerTokensSlashed - _verifierCutAmount); + TokenUtils.burnTokens(_graphToken(), providerTokensSlashed - verifierCutAmount); uint256 provisionFractionSlashed = (providerTokensSlashed * FIXED_POINT_PRECISION) / prov.tokens; // TODO check for rounding issues prov.tokensThawing = (prov.tokensThawing * (FIXED_POINT_PRECISION - provisionFractionSlashed)) / (FIXED_POINT_PRECISION); prov.tokens = prov.tokens - providerTokensSlashed; - serviceProviders[_serviceProvider].tokensProvisioned = - serviceProviders[_serviceProvider].tokensProvisioned - + _serviceProviders[serviceProvider].tokensProvisioned = + _serviceProviders[serviceProvider].tokensProvisioned - providerTokensSlashed; - serviceProviders[_serviceProvider].tokensStaked = - serviceProviders[_serviceProvider].tokensStaked - + _serviceProviders[serviceProvider].tokensStaked = + _serviceProviders[serviceProvider].tokensStaked - providerTokensSlashed; - emit ProvisionSlashed(_serviceProvider, verifier, providerTokensSlashed); + emit ProvisionSlashed(serviceProvider, verifier, providerTokensSlashed); } tokensToSlash = tokensToSlash - providerTokensSlashed; if (tokensToSlash > 0) { DelegationPoolInternal storage pool; if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = legacyDelegationPools[_serviceProvider]; + pool = _legacyDelegationPools[serviceProvider]; } else { - pool = delegationPools[_serviceProvider][verifier]; + pool = _delegationPools[serviceProvider][verifier]; } if (delegationSlashingEnabled) { require(pool.tokens >= tokensToSlash, "insufficient delegated tokens"); @@ -474,55 +427,32 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp pool.tokensThawing = (pool.tokensThawing * (FIXED_POINT_PRECISION - delegationFractionSlashed)) / FIXED_POINT_PRECISION; - emit DelegationSlashed(_serviceProvider, verifier, tokensToSlash); + emit DelegationSlashed(serviceProvider, verifier, tokensToSlash); } else { - emit DelegationSlashingSkipped(_serviceProvider, verifier, tokensToSlash); + emit DelegationSlashingSkipped(serviceProvider, verifier, tokensToSlash); } } } - /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param _operator The address to check for auth - * @param _serviceProvider The service provider on behalf of whom they're claiming to act - * @param _verifier The verifier / data service on which they're claiming to act - */ - function isAuthorized( - address _operator, - address _serviceProvider, - address _verifier - ) public view override returns (bool) { - if (_operator == _serviceProvider) { - return true; - } - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - return legacyOperatorAuth[_serviceProvider][_operator]; - } else { - return operatorAuth[_serviceProvider][_verifier][_operator]; - } + // For backwards compatibility, delegates to the subgraph data service + // (Note this one doesn't have splippage/rounding protection!) + function delegate(address serviceProvider, uint256 tokens) external { + delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); } - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) public view override returns (uint256 tokens) { - return - serviceProviders[serviceProvider].tokensStaked - - serviceProviders[serviceProvider].tokensProvisioned - - serviceProviders[serviceProvider].__DEPRECATED_tokensLocked; + // For backwards compatibility, undelegates from the subgraph data service + function undelegate(address serviceProvider, uint256 shares) external { + undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); } - // provisioned tokens from the service provider that are not being thawed - // `Provision.tokens - Provision.tokensThawing` - function getProviderTokensAvailable( - address _serviceProvider, - address _verifier - ) public view override returns (uint256) { - return provisions[_serviceProvider][_verifier].tokens - provisions[_serviceProvider][_verifier].tokensThawing; + // For backwards compatibility, withdraws delegated tokens from the subgraph data service + function withdrawDelegated(address serviceProvider, address newServiceProvider) external { + withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0); } - function setAllowedLockedVerifier(address _verifier, bool _allowed) external onlyGovernor { - allowedLockedVerifiers[_verifier] = _allowed; - emit AllowedLockedVerifierSet(_verifier, _allowed); + function setAllowedLockedVerifier(address verifier, bool allowed) external onlyGovernor { + _allowedLockedVerifiers[verifier] = allowed; + emit AllowedLockedVerifierSet(verifier, allowed); } /** @@ -534,152 +464,159 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp _withdraw(msg.sender); } - function delegate( - address _serviceProvider, - address _verifier, - uint256 _tokens, - uint256 _minSharesOut - ) public override notPartialPaused { - // Transfer tokens to stake from caller to this contract - TokenUtils.pullTokens(_graphToken(), msg.sender, _tokens); - _delegate(_serviceProvider, _verifier, _tokens, _minSharesOut); + /** + * @notice Add tokens to a delegation pool (without getting shares). + * Used by data services to pay delegation fees/rewards. + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to add to the delegation pool + */ + function addToDelegationPool( + address serviceProvider, + address verifier, + uint256 tokens + ) external override notPartialPaused { + if (tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + DelegationPoolInternal storage pool; + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = _legacyDelegationPools[serviceProvider]; + } else { + pool = _delegationPools[serviceProvider][verifier]; + } + pool.tokens = pool.tokens + tokens; + emit TokensAddedToDelegationPool(serviceProvider, verifier, tokens); } - // For backwards compatibility, delegates to the subgraph data service - // (Note this one doesn't have splippage/rounding protection!) - function delegate(address _serviceProvider, uint256 _tokens) external { - delegate(_serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, _tokens, 0); + function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { + delegationSlashingEnabled = enabled; + emit DelegationSlashingEnabled(enabled); } - // For backwards compatibility, undelegates from the subgraph data service - function undelegate(address _serviceProvider, uint256 _shares) external { - undelegate(_serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, _shares); + // To be called at the end of the transition period, to set the deprecated thawing period to 0 + function clearThawingPeriod() external onlyGovernor { + __DEPRECATED_thawingPeriod = 0; + emit ParameterUpdated("thawingPeriod"); } - // For backwards compatibility, withdraws delegated tokens from the subgraph data service - function withdrawDelegated(address _serviceProvider, address _newServiceProvider) external { - withdrawDelegated(_serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, _newServiceProvider, 0); + function setMaxThawingPeriod(uint64 maxThawingPeriod) external override onlyGovernor { + maxThawingPeriod = _maxThawingPeriod; + emit ParameterUpdated("maxThawingPeriod"); } - function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) internal { - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - // TODO: remove this after L2 transfer tool for delegation is removed - if (_tokens < MIN_DELEGATION) { - revert HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens); - } - if (provisions[_serviceProvider][_verifier].tokens == 0) { - revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); + /** + * @notice Get the amount of service provider's tokens in a provision that have finished thawing + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + */ + function getThawedTokens(address serviceProvider, address verifier) external view returns (uint256) { + Provision storage prov = _provisions[serviceProvider][verifier]; + if (prov.nThawRequests == 0) { + return 0; } - - DelegationPoolInternal storage pool; - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = legacyDelegationPools[_serviceProvider]; - } else { - pool = delegationPools[_serviceProvider][_verifier]; + bytes32 thawRequestId = prov.firstThawRequestId; + uint256 tokens = 0; + while (thawRequestId != bytes32(0)) { + ThawRequest storage thawRequest = _thawRequests[thawRequestId]; + if (thawRequest.thawingUntil <= block.timestamp) { + tokens += (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; + } else { + break; + } + thawRequestId = thawRequest.next; } - Delegation storage delegation = pool.delegators[msg.sender]; + return tokens; + } - // Calculate shares to issue - uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); - if (shares == 0 || shares < _minSharesOut) { - revert HorizonStakingSlippageProtection(_minSharesOut, shares); + /** + * @notice Deposit tokens on the service provider stake, on behalf of the service provider. + * @param serviceProvider Address of the indexer + * @param tokens Amount of tokens to stake + */ + function stakeTo(address serviceProvider, uint256 tokens) public override notPartialPaused { + if (tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); } - pool.tokens = pool.tokens + _tokens; - pool.shares = pool.shares + shares; + // Transfer tokens to stake from caller to this contract + TokenUtils.pullTokens(_graphToken(), msg.sender, tokens); - delegation.shares = delegation.shares + shares; + // Stake the transferred tokens + _stake(serviceProvider, tokens); + } - emit TokensDelegated(_serviceProvider, _verifier, msg.sender, _tokens); + function delegate( + address serviceProvider, + address verifier, + uint256 tokens, + uint256 minSharesOut + ) public override notPartialPaused { + // Transfer tokens to stake from caller to this contract + TokenUtils.pullTokens(_graphToken(), msg.sender, tokens); + _delegate(serviceProvider, verifier, tokens, minSharesOut); } // undelegate tokens from a service provider // the shares are burned and replaced with shares in the thawing pool - function undelegate(address _serviceProvider, address _verifier, uint256 _shares) public override notPartialPaused { - require(_shares > 0, "!shares"); + function undelegate(address serviceProvider, address verifier, uint256 shares) public override notPartialPaused { + require(shares > 0, "!shares"); DelegationPoolInternal storage pool; - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = legacyDelegationPools[_serviceProvider]; + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = _legacyDelegationPools[serviceProvider]; } else { - pool = delegationPools[_serviceProvider][_verifier]; + pool = _delegationPools[serviceProvider][verifier]; } Delegation storage delegation = pool.delegators[msg.sender]; - require(delegation.shares >= _shares, "!shares-avail"); + require(delegation.shares >= shares, "!shares-avail"); - uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; + uint256 tokens = (shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); pool.tokensThawing = pool.tokensThawing + tokens; - pool.shares = pool.shares - _shares; + pool.shares = pool.shares - shares; pool.sharesThawing = pool.sharesThawing + thawingShares; - delegation.shares = delegation.shares - _shares; + delegation.shares = delegation.shares - shares; // TODO: remove this when L2 transfer tools are removed if (delegation.shares != 0) { uint256 remainingTokens = (delegation.shares * (pool.tokens - pool.tokensThawing)) / pool.shares; require(remainingTokens >= MIN_DELEGATION, "!minimum-delegation"); } bytes32 thawRequestId = keccak256( - abi.encodePacked(_serviceProvider, _verifier, msg.sender, delegation.nextThawRequestNonce) + abi.encodePacked(serviceProvider, verifier, msg.sender, delegation.nextThawRequestNonce) ); delegation.nextThawRequestNonce += 1; - ThawRequest storage thawRequest = thawRequests[thawRequestId]; + ThawRequest storage thawRequest = _thawRequests[thawRequestId]; thawRequest.shares = thawingShares; thawRequest.thawingUntil = uint64( - block.timestamp + uint256(provisions[_serviceProvider][_verifier].thawingPeriod) + block.timestamp + uint256(_provisions[serviceProvider][verifier].thawingPeriod) ); require(delegation.nThawRequests < MAX_THAW_REQUESTS, "max thaw requests"); if (delegation.nThawRequests == 0) { delegation.firstThawRequestId = thawRequestId; } else { - thawRequests[delegation.lastThawRequestId].next = thawRequestId; + _thawRequests[delegation.lastThawRequestId].next = thawRequestId; } delegation.lastThawRequestId = thawRequestId; unchecked { delegation.nThawRequests += 1; } - emit TokensUndelegated(_serviceProvider, _verifier, msg.sender, tokens); - } - - /** - * @notice Add tokens to a delegation pool (without getting shares). - * Used by data services to pay delegation fees/rewards. - * @param _serviceProvider The service provider address - * @param _verifier The verifier address for which the tokens are provisioned - * @param _tokens The amount of tokens to add to the delegation pool - */ - function addToDelegationPool( - address _serviceProvider, - address _verifier, - uint256 _tokens - ) external override notPartialPaused { - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - DelegationPoolInternal storage pool; - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = legacyDelegationPools[_serviceProvider]; - } else { - pool = delegationPools[_serviceProvider][_verifier]; - } - pool.tokens = pool.tokens + _tokens; - emit TokensAddedToDelegationPool(_serviceProvider, _verifier, _tokens); + emit TokensUndelegated(serviceProvider, verifier, msg.sender, tokens); } function withdrawDelegated( - address _serviceProvider, - address _verifier, - address _newServiceProvider, - uint256 _minSharesForNewProvider + address serviceProvider, + address verifier, + address newServiceProvider, + uint256 minSharesForNewProvider ) public override notPartialPaused { DelegationPoolInternal storage pool; - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = legacyDelegationPools[_serviceProvider]; + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = _legacyDelegationPools[serviceProvider]; } else { - pool = delegationPools[_serviceProvider][_verifier]; + pool = _delegationPools[serviceProvider][verifier]; } Delegation storage delegation = pool.delegators[msg.sender]; uint256 thawedTokens = 0; @@ -689,13 +626,13 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp require(delegation.nThawRequests > 0, "no thaw requests"); bytes32 thawRequestId = delegation.firstThawRequestId; while (thawRequestId != bytes32(0)) { - ThawRequest storage thawRequest = thawRequests[thawRequestId]; + ThawRequest storage thawRequest = _thawRequests[thawRequestId]; if (thawRequest.thawingUntil <= block.timestamp) { uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; tokensThawing = tokensThawing - tokens; sharesThawing = sharesThawing - thawRequest.shares; thawedTokens = thawedTokens + tokens; - delete thawRequests[thawRequestId]; + delete _thawRequests[thawRequestId]; delegation.firstThawRequestId = thawRequest.next; delegation.nThawRequests -= 1; if (delegation.nThawRequests == 0) { @@ -711,51 +648,85 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp pool.sharesThawing = sharesThawing; pool.tokensThawing = tokensThawing; - if (_newServiceProvider != address(0)) { - _delegate(_newServiceProvider, _verifier, thawedTokens, _minSharesForNewProvider); + if (newServiceProvider != address(0)) { + _delegate(newServiceProvider, verifier, thawedTokens, minSharesForNewProvider); } else { TokenUtils.pushTokens(_graphToken(), msg.sender, thawedTokens); } - emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, thawedTokens); + emit DelegatedTokensWithdrawn(serviceProvider, verifier, msg.sender, thawedTokens); } - function setDelegationSlashingEnabled(bool _enabled) external override onlyGovernor { - delegationSlashingEnabled = _enabled; - emit DelegationSlashingEnabled(_enabled); + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param operator The address to check for auth + * @param serviceProvider The service provider on behalf of whom they're claiming to act + * @param verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized( + address operator, + address serviceProvider, + address verifier + ) public view override returns (bool) { + if (operator == serviceProvider) { + return true; + } + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return _legacyOperatorAuth[serviceProvider][operator]; + } else { + return _operatorAuth[serviceProvider][verifier][operator]; + } } - // To be called at the end of the transition period, to set the deprecated thawing period to 0 - function clearThawingPeriod() external onlyGovernor { - __DEPRECATED_thawingPeriod = 0; - emit ParameterUpdated("thawingPeriod"); + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address serviceProvider) public view override returns (uint256 tokens) { + return + _serviceProviders[serviceProvider].tokensStaked - + _serviceProviders[serviceProvider].tokensProvisioned - + _serviceProviders[serviceProvider].__DEPRECATED_tokensLocked; } - function setMaxThawingPeriod(uint64 _maxThawingPeriod) external override onlyGovernor { - maxThawingPeriod = _maxThawingPeriod; - emit ParameterUpdated("maxThawingPeriod"); + // provisioned tokens from the service provider that are not being thawed + // `Provision.tokens - Provision.tokensThawing` + function getProviderTokensAvailable( + address serviceProvider, + address verifier + ) public view override returns (uint256) { + return _provisions[serviceProvider][verifier].tokens - _provisions[serviceProvider][verifier].tokensThawing; } - /** - * @dev Withdraw indexer tokens once the thawing period has passed. - * @param _indexer Address of indexer to withdraw funds from - */ - function _withdraw(address _indexer) private { - // Get tokens available for withdraw and update balance - ServiceProviderInternal storage sp = serviceProviders[_indexer]; - uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; - require(tokensToWithdraw > 0, "!tokens"); - require(block.number >= sp.__DEPRECATED_tokensLockedUntil, "locked"); + function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) internal { + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + // TODO: remove this after L2 transfer tool for delegation is removed + if (_tokens < MIN_DELEGATION) { + revert HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens); + } + if (_provisions[_serviceProvider][_verifier].tokens == 0) { + revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); + } - // Reset locked tokens - sp.__DEPRECATED_tokensLocked = 0; - sp.__DEPRECATED_tokensLockedUntil = 0; + DelegationPoolInternal storage pool; + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + pool = _legacyDelegationPools[_serviceProvider]; + } else { + pool = _delegationPools[_serviceProvider][_verifier]; + } + Delegation storage delegation = pool.delegators[msg.sender]; - sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; + // Calculate shares to issue + uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); + if (shares == 0 || shares < _minSharesOut) { + revert HorizonStakingSlippageProtection(_minSharesOut, shares); + } - // Return tokens to the indexer - TokenUtils.pushTokens(_graphToken(), _indexer, tokensToWithdraw); + pool.tokens = pool.tokens + _tokens; + pool.shares = pool.shares + shares; - emit StakeWithdrawn(_indexer, tokensToWithdraw); + delegation.shares = delegation.shares + shares; + + emit TokensDelegated(_serviceProvider, _verifier, msg.sender, _tokens); } /** @@ -770,8 +741,8 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp ) internal { require(_tokens >= MIN_PROVISION_SIZE, "!tokens"); require(_maxVerifierCut <= MAX_MAX_VERIFIER_CUT, "maxVerifierCut too high"); - require(_thawingPeriod <= maxThawingPeriod, "thawingPeriod too high"); - provisions[_serviceProvider][_verifier] = Provision({ + require(_thawingPeriod <= _maxThawingPeriod, "thawingPeriod too high"); + _provisions[_serviceProvider][_verifier] = Provision({ tokens: _tokens, tokensThawing: 0, sharesThawing: 0, @@ -785,26 +756,26 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp thawingPeriodPending: _thawingPeriod }); - ServiceProviderInternal storage sp = serviceProviders[_serviceProvider]; + ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; sp.tokensProvisioned = sp.tokensProvisioned + _tokens; emit ProvisionCreated(_serviceProvider, _verifier, _tokens, _maxVerifierCut, _thawingPeriod); } function _fulfillThawRequests(address _serviceProvider, address _verifier, uint256 _tokens) internal { - Provision storage prov = provisions[_serviceProvider][_verifier]; + Provision storage prov = _provisions[_serviceProvider][_verifier]; uint256 tokensRemaining = _tokens; uint256 sharesThawing = prov.sharesThawing; uint256 tokensThawing = prov.tokensThawing; while (tokensRemaining > 0) { require(prov.nThawRequests > 0, "not enough thawed tokens"); bytes32 thawRequestId = prov.firstThawRequestId; - ThawRequest storage thawRequest = thawRequests[thawRequestId]; + ThawRequest storage thawRequest = _thawRequests[thawRequestId]; require(thawRequest.thawingUntil <= block.timestamp, "thawing period not over"); uint256 thawRequestTokens = (thawRequest.shares * tokensThawing) / sharesThawing; if (thawRequestTokens <= tokensRemaining) { tokensRemaining = tokensRemaining - thawRequestTokens; - delete thawRequests[thawRequestId]; + delete _thawRequests[thawRequestId]; prov.firstThawRequestId = thawRequest.next; prov.nThawRequests -= 1; tokensThawing = tokensThawing - thawRequestTokens; @@ -829,11 +800,11 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp prov.sharesThawing = sharesThawing; prov.tokensThawing = tokensThawing; prov.tokens = prov.tokens - _tokens; - serviceProviders[_serviceProvider].tokensProvisioned -= _tokens; + _serviceProviders[_serviceProvider].tokensProvisioned -= _tokens; } function _addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) internal { - Provision storage prov = provisions[_serviceProvider][_verifier]; + Provision storage prov = _provisions[_serviceProvider][_verifier]; if (_tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } @@ -845,8 +816,8 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp } prov.tokens = prov.tokens + _tokens; - serviceProviders[_serviceProvider].tokensProvisioned = - serviceProviders[_serviceProvider].tokensProvisioned + + _serviceProviders[_serviceProvider].tokensProvisioned = + _serviceProviders[_serviceProvider].tokensProvisioned + _tokens; emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); } @@ -859,7 +830,7 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp */ function _stake(address _serviceProvider, uint256 _tokens) internal { // Deposit tokens into the indexer stake - serviceProviders[_serviceProvider].tokensStaked = serviceProviders[_serviceProvider].tokensStaked + _tokens; + _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; emit StakeDeposited(_serviceProvider, _tokens); } @@ -867,4 +838,27 @@ contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUp function _graphToken() internal view returns (IGraphToken) { return IGraphToken(GRAPH_TOKEN); } + + /** + * @dev Withdraw indexer tokens once the thawing period has passed. + * @param _indexer Address of indexer to withdraw funds from + */ + function _withdraw(address _indexer) private { + // Get tokens available for withdraw and update balance + ServiceProviderInternal storage sp = _serviceProviders[_indexer]; + uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; + require(tokensToWithdraw > 0, "!tokens"); + require(block.number >= sp.__DEPRECATED_tokensLockedUntil, "locked"); + + // Reset locked tokens + sp.__DEPRECATED_tokensLocked = 0; + sp.__DEPRECATED_tokensLockedUntil = 0; + + sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; + + // Return tokens to the indexer + TokenUtils.pushTokens(_graphToken(), _indexer, tokensToWithdraw); + + emit StakeWithdrawn(_indexer, tokensToWithdraw); + } } diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 0183e73f9..12a685277 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -29,9 +29,9 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStaki } constructor( - address _controller, - address _subgraphDataServiceAddress - ) StakingBackwardsCompatibility(_controller, _subgraphDataServiceAddress) {} + address controller, + address subgraphDataServiceAddress + ) StakingBackwardsCompatibility(controller, subgraphDataServiceAddress) {} /** * @notice Receive ETH into the Staking contract: this will always revert @@ -41,78 +41,28 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStaki revert("RECEIVE_ETH_NOT_ALLOWED"); } - // total staked tokens to the provider - // `ServiceProvider.tokensStaked - function getStake(address serviceProvider) external view override returns (uint256) { - return serviceProviders[serviceProvider].tokensStaked; - } - - // provisioned tokens from delegators that are not being thawed - // `Provision.delegatedTokens - Provision.delegatedTokensThawing` - function getDelegatedTokensAvailable( - address _serviceProvider, - address _verifier - ) public view override returns (uint256) { - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - return - legacyDelegationPools[_serviceProvider].tokens - - (legacyDelegationPools[_serviceProvider].tokensThawing); - } - return - delegationPools[_serviceProvider][_verifier].tokens - - (delegationPools[_serviceProvider][_verifier].tokensThawing); - } - - // provisioned tokens that are not being thawed (including provider tokens and delegation) - function getTokensAvailable( - address _serviceProvider, - address _verifier, - uint32 _delegationRatio - ) external view override returns (uint256) { - uint256 providerTokens = provisions[_serviceProvider][_verifier].tokens; - uint256 tokensDelegatedMax = providerTokens * (uint256(_delegationRatio)); - uint256 tokensDelegatedCapacity = MathUtils.min( - getDelegatedTokensAvailable(_serviceProvider, _verifier), - tokensDelegatedMax - ); - return providerTokens - provisions[_serviceProvider][_verifier].tokensThawing + tokensDelegatedCapacity; - } - - function getServiceProvider(address serviceProvider) external view override returns (ServiceProvider memory) { - ServiceProvider memory sp; - ServiceProviderInternal storage spInternal = serviceProviders[serviceProvider]; - sp.tokensStaked = spInternal.tokensStaked; - sp.tokensProvisioned = spInternal.tokensProvisioned; - sp.nextThawRequestNonce = spInternal.nextThawRequestNonce; - return sp; - } - /** * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. - * @param _operator Address to authorize or unauthorize - * @param _verifier The verifier / data service on which they'll be allowed to operate - * @param _allowed Whether the operator is authorized or not + * @param operator Address to authorize or unauthorize + * @param verifier The verifier / data service on which they'll be allowed to operate + * @param allowed Whether the operator is authorized or not */ - function setOperator(address _operator, address _verifier, bool _allowed) external override { - require(_operator != msg.sender, "operator == sender"); - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - legacyOperatorAuth[msg.sender][_operator] = _allowed; + function setOperator(address operator, address verifier, bool allowed) external override { + require(operator != msg.sender, "operator == sender"); + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + _legacyOperatorAuth[msg.sender][operator] = allowed; } else { - operatorAuth[msg.sender][_verifier][_operator] = _allowed; + _operatorAuth[msg.sender][verifier][operator] = allowed; } - emit OperatorSet(msg.sender, _operator, _verifier, _allowed); + emit OperatorSet(msg.sender, operator, verifier, allowed); } // for vesting contracts - function setOperatorLocked(address _operator, address _verifier, bool _allowed) external override { - require(_operator != msg.sender, "operator == sender"); - require(allowedLockedVerifiers[_verifier], "VERIFIER_NOT_ALLOWED"); - operatorAuth[msg.sender][_verifier][_operator] = _allowed; - emit OperatorSet(msg.sender, _operator, _verifier, _allowed); - } - - function getMaxThawingPeriod() external view override returns (uint64) { - return maxThawingPeriod; + function setOperatorLocked(address operator, address verifier, bool allowed) external override { + require(operator != msg.sender, "operator == sender"); + require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); + _operatorAuth[msg.sender][verifier][operator] = allowed; + emit OperatorSet(msg.sender, operator, verifier, allowed); } /** @@ -120,45 +70,89 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStaki * @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. - * @param _from Token sender in L1 - * @param _amount Amount of tokens that were transferred - * @param _data ABI-encoded callhook data which must include a uint8 code and either a ReceiveIndexerStakeData or ReceiveDelegationData struct. + * @param from Token sender in L1 + * @param amount Amount of tokens that were transferred + * @param data ABI-encoded callhook data which must include a uint8 code and either a ReceiveIndexerStakeData or ReceiveDelegationData struct. */ function onTokenTransfer( - address _from, - uint256 _amount, - bytes calldata _data + address from, + uint256 amount, + bytes calldata data ) external override notPartialPaused onlyL2Gateway { - require(_from == counterpartStakingAddress, "ONLY_L1_STAKING_THROUGH_BRIDGE"); - (uint8 code, bytes memory functionData) = abi.decode(_data, (uint8, bytes)); + require(from == _counterpartStakingAddress, "ONLY_L1_STAKING_THROUGH_BRIDGE"); + (uint8 code, bytes memory functionData) = abi.decode(data, (uint8, bytes)); if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_INDEXER_STAKE_CODE)) { IL2StakingTypes.ReceiveIndexerStakeData memory indexerData = abi.decode( functionData, (IL2StakingTypes.ReceiveIndexerStakeData) ); - _receiveIndexerStake(_amount, indexerData); + _receiveIndexerStake(amount, indexerData); } else if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE)) { IL2StakingTypes.ReceiveDelegationData memory delegationData = abi.decode( functionData, (IL2StakingTypes.ReceiveDelegationData) ); - _receiveDelegation(_amount, delegationData); + _receiveDelegation(amount, delegationData); } else { revert("INVALID_CODE"); } } + function setDelegationFeeCut( + address serviceProvider, + address verifier, + uint256 feeType, + uint256 feeCut + ) external override { + delegationFeeCut[serviceProvider][verifier][feeType] = feeCut; + emit DelegationFeeCutSet(serviceProvider, verifier, feeType, feeCut); + } + + // total staked tokens to the provider + // `ServiceProvider.tokensStaked + function getStake(address serviceProvider) external view override returns (uint256) { + return _serviceProviders[serviceProvider].tokensStaked; + } + + // provisioned tokens that are not being thawed (including provider tokens and delegation) + function getTokensAvailable( + address serviceProvider, + address verifier, + uint32 delegationRatio + ) external view override returns (uint256) { + uint256 providerTokens = _provisions[serviceProvider][verifier].tokens; + uint256 tokensDelegatedMax = providerTokens * (uint256(delegationRatio)); + uint256 tokensDelegatedCapacity = MathUtils.min( + getDelegatedTokensAvailable(serviceProvider, verifier), + tokensDelegatedMax + ); + return providerTokens - _provisions[serviceProvider][verifier].tokensThawing + tokensDelegatedCapacity; + } + + function getServiceProvider(address serviceProvider) external view override returns (ServiceProvider memory) { + ServiceProvider memory sp; + ServiceProviderInternal storage spInternal = _serviceProviders[serviceProvider]; + sp.tokensStaked = spInternal.tokensStaked; + sp.tokensProvisioned = spInternal.tokensProvisioned; + sp.nextThawRequestNonce = spInternal.nextThawRequestNonce; + return sp; + } + + function getMaxThawingPeriod() external view override returns (uint64) { + return _maxThawingPeriod; + } + function getDelegationPool( - address _serviceProvider, - address _verifier + address serviceProvider, + address verifier ) external view override returns (DelegationPool memory) { DelegationPool memory pool; DelegationPoolInternal storage poolInternal; - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - poolInternal = legacyDelegationPools[_serviceProvider]; + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + poolInternal = _legacyDelegationPools[serviceProvider]; } else { - poolInternal = delegationPools[_serviceProvider][_verifier]; + poolInternal = _delegationPools[serviceProvider][verifier]; } pool.tokens = poolInternal.tokens; pool.shares = poolInternal.shares; @@ -168,44 +162,47 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStaki } function getDelegation( - address _delegator, - address _serviceProvider, - address _verifier + address delegator, + address serviceProvider, + address verifier ) external view override returns (Delegation memory) { - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - return legacyDelegationPools[_serviceProvider].delegators[_delegator]; + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return _legacyDelegationPools[serviceProvider].delegators[delegator]; } else { - return delegationPools[_serviceProvider][_verifier].delegators[_delegator]; + return _delegationPools[serviceProvider][verifier].delegators[delegator]; } } - function getThawRequest(bytes32 _thawRequestId) external view returns (ThawRequest memory) { - return thawRequests[_thawRequestId]; - } - - function getProvision( - address _serviceProvider, - address _verifier - ) external view override returns (Provision memory) { - return provisions[_serviceProvider][_verifier]; + function getThawRequest(bytes32 thawRequestId) external view returns (ThawRequest memory) { + return _thawRequests[thawRequestId]; } - function setDelegationFeeCut( - address _serviceProvider, - address _verifier, - uint256 _feeType, - uint256 _feeCut - ) external override { - delegationFeeCut[_serviceProvider][_verifier][_feeType] = _feeCut; - emit DelegationFeeCutSet(_serviceProvider, _verifier, _feeType, _feeCut); + function getProvision(address serviceProvider, address verifier) external view override returns (Provision memory) { + return _provisions[serviceProvider][verifier]; } function getDelegationFeeCut( - address _serviceProvider, - address _verifier, - uint256 _feeType + address serviceProvider, + address verifier, + uint256 feeType ) external view override returns (uint256) { - return delegationFeeCut[_serviceProvider][_verifier][_feeType]; + return delegationFeeCut[serviceProvider][verifier][feeType]; + } + + // provisioned tokens from delegators that are not being thawed + // `Provision.delegatedTokens - Provision.delegatedTokensThawing` + function getDelegatedTokensAvailable( + address serviceProvider, + address verifier + ) public view override returns (uint256) { + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return + _legacyDelegationPools[serviceProvider].tokens - + (_legacyDelegationPools[serviceProvider].tokensThawing); + } + return + _delegationPools[serviceProvider][verifier].tokens - + (_delegationPools[serviceProvider][verifier].tokensThawing); } /** @@ -219,9 +216,9 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStaki uint256 _amount, IL2StakingTypes.ReceiveIndexerStakeData memory _indexerData ) internal { - address _indexer = _indexerData.indexer; + address indexer = _indexerData.indexer; // Deposit tokens into the indexer stake - _stake(_indexer, _amount); + _stake(indexer, _amount); } /** @@ -237,7 +234,7 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStaki IL2StakingTypes.ReceiveDelegationData memory _delegationData ) internal { // Get the delegation pool of the indexer - DelegationPoolInternal storage pool = legacyDelegationPools[_delegationData.indexer]; + DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; Delegation storage delegation = pool.delegators[_delegationData.delegator]; // Calculate shares to issue (without applying any delegation tax) diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 80e25f6ae..a640568ef 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -7,6 +7,9 @@ import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; import { Managed } from "./utilities/Managed.sol"; +// TODO: create custom var-name-mixedcase +/* solhint-disable var-name-mixedcase */ + /** * @title HorizonStakingV1Storage * @notice This contract holds all the storage variables for the Staking contract, version 1 @@ -34,7 +37,7 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { uint32 internal __DEPRECATED_protocolPercentage; /// @dev Period for allocation to be finalized - uint32 private __DEPRECATED_channelDisputeEpochs; // solhint-disable-line var-name-mixedcase + uint32 private __DEPRECATED_channelDisputeEpochs; /// @dev Maximum allocation time. Deprecated, allocations now live on the subgraph service contract. uint32 internal __DEPRECATED_maxAllocationEpochs; @@ -50,25 +53,26 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { uint32 internal __DEPRECATED_alphaDenominator; /// @dev Service provider stakes : serviceProviderAddress => ServiceProvider - mapping(address => ServiceProviderInternal) internal serviceProviders; + mapping(address serviceProvider => ServiceProviderInternal details) internal _serviceProviders; /// @dev Allocations : allocationID => Allocation /// Deprecated, now applied on the SubgraphService - mapping(address => IStakingBackwardsCompatibility.Allocation) internal __DEPRECATED_allocations; + mapping(address allocationId => IStakingBackwardsCompatibility.Allocation allocation) + internal __DEPRECATED_allocations; /// @dev Subgraph Allocations: subgraphDeploymentID => tokens /// Deprecated, now applied on the SubgraphService - mapping(bytes32 => uint256) internal __DEPRECATED_subgraphAllocations; + mapping(bytes32 subgraphDeploymentId => uint256 tokens) internal __DEPRECATED_subgraphAllocations; /// @dev Rebate pools : epoch => Pool /// Deprecated. - mapping(uint256 => uint256) private __DEPRECATED_rebates; // solhint-disable-line var-name-mixedcase + mapping(uint256 epoch => uint256 rebates) private __DEPRECATED_rebates; // -- Slashing -- /// @dev List of addresses allowed to slash stakes /// Deprecated, now each verifier can slash the corresponding provision. - mapping(address => bool) internal __DEPRECATED_slashers; + mapping(address slasher => bool allowed) internal __DEPRECATED_slashers; // -- Delegation -- @@ -77,7 +81,7 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { uint32 internal __DEPRECATED_delegationRatio; /// @dev Time in blocks an indexer needs to wait to change delegation parameters (deprecated) - uint32 internal __DEPRECATED_delegationParametersCooldown; // solhint-disable-line var-name-mixedcase + uint32 internal __DEPRECATED_delegationParametersCooldown; /// @dev Time in epochs a delegator needs to wait to withdraw delegated stake /// Deprecated, now only enforced during a transition period @@ -90,24 +94,24 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { /// @dev Delegation pools : serviceProvider => DelegationPoolInternal /// These are for the subgraph data service. - mapping(address => DelegationPoolInternal) internal legacyDelegationPools; + mapping(address serviceProvider => DelegationPoolInternal delegationPool) internal _legacyDelegationPools; // -- Operators -- /// @dev Legacy operator auth : indexer => operator => is authorized - mapping(address => mapping(address => bool)) internal legacyOperatorAuth; + mapping(address legacyOperator => mapping(address serviceProvider => bool authorized)) internal _legacyOperatorAuth; // -- Asset Holders -- /// @dev DEPRECATED: Allowed AssetHolders: assetHolder => is allowed - mapping(address => bool) private __DEPRECATED_assetHolders; // solhint-disable-line var-name-mixedcase + mapping(address assetHolder => bool allowed) private __DEPRECATED_assetHolders; /// @dev Destination of accrued rewards : beneficiary => rewards destination /// Deprecated, defined by each data service as needed - mapping(address => address) internal __DEPRECATED_rewardsDestination; + mapping(address serviceProvider => address rewardsDestination) internal __DEPRECATED_rewardsDestination; /// @dev Address of the counterpart Staking contract on L1/L2 - address internal counterpartStakingAddress; + address internal _counterpartStakingAddress; /// @dev Address of the StakingExtension implementation address internal __DEPRECATED_extensionImpl; @@ -116,11 +120,11 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { uint32 internal __DEPRECATED_lambdaDenominator; /// Maximum thawing period, in seconds, for a provision - uint64 internal maxThawingPeriod; + uint64 internal _maxThawingPeriod; /// @dev Provisions from each service provider for each data service /// ServiceProvider => Verifier => Provision - mapping(address => mapping(address => Provision)) internal provisions; + mapping(address serviceProvider => mapping(address verifier => Provision provision)) internal _provisions; /// @dev Delegation fee cuts for each service provider on each provision, by fee type: /// ServiceProvider => Verifier => Fee Type => Fee Cut. @@ -128,19 +132,22 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { /// This is in PPM and is the cut taken by the indexer from the fees that correspond to delegators. /// (based on stake vs delegated stake proportion). /// The cuts are applied in GraphPayments so apply to all data services that use it. - mapping(address => mapping(address => mapping(uint256 => uint256))) public delegationFeeCut; + mapping(address serviceProvider => mapping(address verifier => mapping(uint256 feeType => uint256 feeCut))) + public delegationFeeCut; - mapping(bytes32 => ThawRequest) internal thawRequests; + mapping(bytes32 thawRequestId => ThawRequest thawRequest) internal _thawRequests; // indexer => verifier => operator => authorized - mapping(address => mapping(address => mapping(address => bool))) internal operatorAuth; + mapping(address serviceProvider => mapping(address verifier => mapping(address operator => bool authorized))) + internal _operatorAuth; // governance enables or disables delegation slashing with this flag bool public delegationSlashingEnabled; // delegation pools for each service provider and verifier - mapping(address => mapping(address => DelegationPoolInternal)) internal delegationPools; + mapping(address serviceProvider => mapping(address verifier => DelegationPoolInternal delegationPool)) + internal _delegationPools; // allowed verifiers for locked provisions (i.e. from GraphTokenLockWallets) - mapping(address => bool) internal allowedLockedVerifiers; + mapping(address verifier => bool allowed) internal _allowedLockedVerifiers; } diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 0d8c2749e..ea51f372c 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -38,18 +38,18 @@ abstract contract StakingBackwardsCompatibility is address public immutable SUBGRAPH_DATA_SERVICE_ADDRESS; - constructor(address _controller, address _subgraphDataServiceAddress) Managed(_controller) { - SUBGRAPH_DATA_SERVICE_ADDRESS = _subgraphDataServiceAddress; + constructor(address controller, address subgraphDataServiceAddress) Managed(controller) { + SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; } /** * @notice Set the address of the counterpart (L1 or L2) staking contract. * @dev This function can only be called by the governor. * TODO: Remove after L2 transition period - * @param _counterpart Address of the counterpart staking contract in the other chain, without any aliasing. + * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. */ - function setCounterpartStakingAddress(address _counterpart) external override onlyGovernor { - counterpartStakingAddress = _counterpart; + function setCounterpartStakingAddress(address counterpart) external override onlyGovernor { + _counterpartStakingAddress = counterpart; emit ParameterUpdated("counterpartStakingAddress"); } @@ -59,11 +59,11 @@ abstract contract StakingBackwardsCompatibility is * Presenting a bad proof is subject to slashable condition. * To opt out of rewards set _poi to 0x0 * @dev TODO: Remove after Horizon transition period - * @param _allocationID The allocation identifier - * @param _poi Proof of indexing submitted for the allocated period + * @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); + function closeAllocation(address allocationID, bytes32 poi) external override notPaused { + _closeAllocation(allocationID, poi); } /** @@ -73,27 +73,27 @@ abstract contract StakingBackwardsCompatibility is * 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. * TODO: Remove after Horizon transition period - * @param _tokens Amount of tokens to collect - * @param _allocationID Allocation where the tokens will be assigned + * @param tokens Amount of tokens to collect + * @param allocationID Allocation where the tokens will be assigned */ - function collect(uint256 _tokens, address _allocationID) external override { + function collect(uint256 tokens, address allocationID) external override { // Allocation identifier validation - require(_allocationID != address(0), "!alloc"); + require(allocationID != address(0), "!alloc"); // Allocation must exist - AllocationState allocState = _getAllocationState(_allocationID); + AllocationState allocState = _getAllocationState(allocationID); require(allocState != AllocationState.Null, "!collect"); // If the query fees are zero, we don't want to revert // but we also don't need to do anything, so just return - if (_tokens == 0) { + if (tokens == 0) { return; } - Allocation storage alloc = __DEPRECATED_allocations[_allocationID]; + Allocation storage alloc = __DEPRECATED_allocations[allocationID]; bytes32 subgraphDeploymentID = alloc.subgraphDeploymentID; - uint256 queryFees = _tokens; // Tokens collected from the channel + uint256 queryFees = tokens; // Tokens collected from the channel uint256 protocolTax = 0; // Tokens burnt as protocol tax uint256 curationFees = 0; // Tokens distributed to curators as curation fees uint256 queryRebates = 0; // Tokens to distribute to indexer @@ -160,9 +160,9 @@ abstract contract StakingBackwardsCompatibility is msg.sender, alloc.indexer, subgraphDeploymentID, - _allocationID, + allocationID, _epochManager().currentEpoch(), - _tokens, + tokens, protocolTax, curationFees, queryFees, @@ -174,69 +174,172 @@ abstract contract StakingBackwardsCompatibility is /** * @notice Return if allocationID is used. * @dev TODO: Remove after Horizon transition period - * @param _allocationID Address used as signer by the indexer for an allocation + * @param allocationID Address used as signer by the indexer for an allocation * @return True if allocationID already used */ - function isAllocation(address _allocationID) external view override returns (bool) { - return _getAllocationState(_allocationID) != AllocationState.Null; + function isAllocation(address allocationID) external view override returns (bool) { + return _getAllocationState(allocationID) != AllocationState.Null; } /** * @notice Return the allocation by ID. * @dev TODO: Remove after Horizon transition period - * @param _allocationID Address used as allocation identifier + * @param allocationID Address used as allocation identifier * @return Allocation data */ - function getAllocation(address _allocationID) external view override returns (Allocation memory) { - return __DEPRECATED_allocations[_allocationID]; + function getAllocation(address allocationID) external view override returns (Allocation memory) { + return __DEPRECATED_allocations[allocationID]; } /** * @notice Return the current state of an allocation * @dev TODO: Remove after Horizon transition period - * @param _allocationID Allocation identifier + * @param allocationID Allocation identifier * @return AllocationState enum with the state of the allocation */ - function getAllocationState(address _allocationID) external view override returns (AllocationState) { - return _getAllocationState(_allocationID); + 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 + * @param subgraphDeploymentID Deployment ID for the subgraph * @return Total tokens allocated to subgraph */ - function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { - return __DEPRECATED_subgraphAllocations[_subgraphDeploymentID]; + function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view override returns (uint256) { + return __DEPRECATED_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 + */ + function getIndexerStakedTokens(address indexer) external view override returns (uint256) { + return _serviceProviders[indexer].tokensStaked; + } + + /** + * @notice Getter that returns if an indexer has any stake. + * @param indexer Address of the indexer + * @return True if indexer has staked tokens + */ + function hasStake(address indexer) external view override returns (bool) { + return _serviceProviders[indexer].tokensStaked > 0; } /** * @notice (Legacy) Return true if operator is allowed for the service provider on the subgraph data service. * @dev TODO: Delete after the transition period - * @param _operator Address of the operator - * @param _serviceProvider Address of the service provider + * @param operator Address of the operator + * @param serviceProvider Address of the service provider * @return True if operator is allowed for indexer, false otherwise */ - function isOperator(address _operator, address _serviceProvider) public view override returns (bool) { - return legacyOperatorAuth[_serviceProvider][_operator]; + function isOperator(address operator, address serviceProvider) public view override returns (bool) { + return _legacyOperatorAuth[serviceProvider][operator]; } /** - * @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 + * @dev Stake tokens on the service provider. + * TODO: Move to HorizonStaking after the transition period + * @param _serviceProvider Address of staking party + * @param _tokens Amount of tokens to stake */ - function getIndexerStakedTokens(address _indexer) external view override returns (uint256) { - return serviceProviders[_indexer].tokensStaked; + function _stake(address _serviceProvider, uint256 _tokens) internal { + // Deposit tokens into the indexer stake + _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; + + emit StakeDeposited(_serviceProvider, _tokens); + } + + function _graphToken() internal view returns (IGraphToken) { + return IGraphToken(GRAPH_TOKEN); + } + + function _curation() internal view returns (ICuration) { + return ICuration(CURATION); + } + + function _rewardsManager() internal view returns (IRewardsManager) { + return IRewardsManager(REWARDS_MANAGER); + } + + function _epochManager() internal view returns (IEpochManager) { + return IEpochManager(EPOCH_MANAGER); } /** - * @notice Getter that returns if an indexer has any stake. - * @param _indexer Address of the indexer - * @return True if indexer has staked tokens + * @dev Collect tax to burn for an amount of tokens. + * @param _tokens Total tokens received used to calculate the amount of tax to collect + * @param _percentage Percentage of tokens to burn as tax + * @return Amount of tax charged + */ + function _collectTax(uint256 _tokens, uint256 _percentage) private returns (uint256) { + // Calculate tokens after tax first, and subtract that, + // to prevent the tax from rounding down to zero + uint256 tokensAfterTax = ((uint256(MAX_PPM) - _percentage) * _tokens) / MAX_PPM; + uint256 tax = _tokens - tokensAfterTax; + TokenUtils.burnTokens(_graphToken(), tax); // Burn tax if any + return tax; + } + + /** + * @dev 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 */ - function hasStake(address _indexer) external view override returns (bool) { - return serviceProviders[_indexer].tokensStaked > 0; + function _updateRewards(bytes32 _subgraphDeploymentID) private returns (uint256) { + IRewardsManager rewardsManager = _rewardsManager(); + if (address(rewardsManager) == address(0)) { + return 0; + } + return rewardsManager.onSubgraphAllocationUpdate(_subgraphDeploymentID); + } + + /** + * @dev Assign rewards for the closed allocation to indexer and delegators. + * @param _allocationID Allocation + * @param _indexer Address of the indexer that did the allocation + */ + function _distributeRewards(address _allocationID, address _indexer) private { + IRewardsManager rewardsManager = _rewardsManager(); + if (address(rewardsManager) == address(0)) { + return; + } + + // Automatically triggers update of rewards snapshot as allocation will change + // after this call. Take rewards mint tokens for the Staking contract to distribute + // between indexer and delegators + uint256 totalRewards = rewardsManager.takeRewards(_allocationID); + if (totalRewards == 0) { + return; + } + + // Calculate delegation rewards and add them to the delegation pool + uint256 delegationRewards = _collectDelegationIndexingRewards(_indexer, totalRewards); + uint256 indexerRewards = totalRewards - delegationRewards; + + // Send the indexer rewards + _sendRewards(indexerRewards, _indexer, __DEPRECATED_rewardsDestination[_indexer] == address(0)); + } + + /** + * @dev Send rewards to the appropriate destination. + * @param _amount Number of rewards tokens + * @param _beneficiary Address of the beneficiary of rewards + * @param _restake Whether to restake or not + */ + function _sendRewards(uint256 _amount, address _beneficiary, bool _restake) private { + if (_amount == 0) return; + + if (_restake) { + // Restake to place fees into the indexer stake + _stake(_beneficiary, _amount); + } else { + // Transfer funds to the beneficiary's designated rewards destination if set + address destination = __DEPRECATED_rewardsDestination[_beneficiary]; + TokenUtils.pushTokens(_graphToken(), destination == address(0) ? _beneficiary : destination, _amount); + } } /** @@ -280,8 +383,8 @@ abstract contract StakingBackwardsCompatibility is } // Free allocated tokens from use - serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated = - serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated - + _serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated = + _serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated - alloc.tokens; // Track total allocations per subgraph @@ -312,7 +415,7 @@ abstract contract StakingBackwardsCompatibility is */ function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; - DelegationPoolInternal storage pool = legacyDelegationPools[_indexer]; + DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; if (pool.tokens > 0 && pool.__DEPRECATED_queryFeeCut < MAX_PPM) { uint256 indexerCut = (uint256(pool.__DEPRECATED_queryFeeCut) * _tokens) / MAX_PPM; delegationRewards = _tokens - indexerCut; @@ -330,7 +433,7 @@ abstract contract StakingBackwardsCompatibility is */ function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; - DelegationPoolInternal storage pool = legacyDelegationPools[_indexer]; + DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; if (pool.tokens > 0 && pool.__DEPRECATED_indexingRewardCut < MAX_PPM) { uint256 indexerCut = (uint256(pool.__DEPRECATED_indexingRewardCut) * _tokens) / MAX_PPM; delegationRewards = _tokens - indexerCut; @@ -377,80 +480,6 @@ abstract contract StakingBackwardsCompatibility is return 0; } - /** - * @dev Collect tax to burn for an amount of tokens. - * @param _tokens Total tokens received used to calculate the amount of tax to collect - * @param _percentage Percentage of tokens to burn as tax - * @return Amount of tax charged - */ - function _collectTax(uint256 _tokens, uint256 _percentage) private returns (uint256) { - // Calculate tokens after tax first, and subtract that, - // to prevent the tax from rounding down to zero - uint256 tokensAfterTax = ((uint256(MAX_PPM) - _percentage) * _tokens) / MAX_PPM; - uint256 tax = _tokens - tokensAfterTax; - TokenUtils.burnTokens(_graphToken(), tax); // Burn tax if any - return tax; - } - - /** - * @dev 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 - */ - function _updateRewards(bytes32 _subgraphDeploymentID) private returns (uint256) { - IRewardsManager rewardsManager = _rewardsManager(); - if (address(rewardsManager) == address(0)) { - return 0; - } - return rewardsManager.onSubgraphAllocationUpdate(_subgraphDeploymentID); - } - - /** - * @dev Assign rewards for the closed allocation to indexer and delegators. - * @param _allocationID Allocation - * @param _indexer Address of the indexer that did the allocation - */ - function _distributeRewards(address _allocationID, address _indexer) private { - IRewardsManager rewardsManager = _rewardsManager(); - if (address(rewardsManager) == address(0)) { - return; - } - - // Automatically triggers update of rewards snapshot as allocation will change - // after this call. Take rewards mint tokens for the Staking contract to distribute - // between indexer and delegators - uint256 totalRewards = rewardsManager.takeRewards(_allocationID); - if (totalRewards == 0) { - return; - } - - // Calculate delegation rewards and add them to the delegation pool - uint256 delegationRewards = _collectDelegationIndexingRewards(_indexer, totalRewards); - uint256 indexerRewards = totalRewards - delegationRewards; - - // Send the indexer rewards - _sendRewards(indexerRewards, _indexer, __DEPRECATED_rewardsDestination[_indexer] == address(0)); - } - - /** - * @dev Send rewards to the appropriate destination. - * @param _amount Number of rewards tokens - * @param _beneficiary Address of the beneficiary of rewards - * @param _restake Whether to restake or not - */ - function _sendRewards(uint256 _amount, address _beneficiary, bool _restake) private { - if (_amount == 0) return; - - if (_restake) { - // Restake to place fees into the indexer stake - _stake(_beneficiary, _amount); - } else { - // Transfer funds to the beneficiary's designated rewards destination if set - address destination = __DEPRECATED_rewardsDestination[_beneficiary]; - TokenUtils.pushTokens(_graphToken(), destination == address(0) ? _beneficiary : destination, _amount); - } - } - /** * @dev Return the current state of an allocation * @param _allocationID Allocation identifier @@ -469,33 +498,4 @@ abstract contract StakingBackwardsCompatibility is return AllocationState.Closed; } - - /** - * @dev Stake tokens on the service provider. - * TODO: Move to HorizonStaking after the transition period - * @param _serviceProvider Address of staking party - * @param _tokens Amount of tokens to stake - */ - function _stake(address _serviceProvider, uint256 _tokens) internal { - // Deposit tokens into the indexer stake - serviceProviders[_serviceProvider].tokensStaked = serviceProviders[_serviceProvider].tokensStaked + _tokens; - - emit StakeDeposited(_serviceProvider, _tokens); - } - - function _graphToken() internal view returns (IGraphToken) { - return IGraphToken(GRAPH_TOKEN); - } - - function _curation() internal view returns (ICuration) { - return ICuration(CURATION); - } - - function _rewardsManager() internal view returns (IRewardsManager) { - return IRewardsManager(REWARDS_MANAGER); - } - - function _epochManager() internal view returns (IEpochManager) { - return IEpochManager(EPOCH_MANAGER); - } } diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index 685c18184..496caca0e 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -7,6 +7,9 @@ import { IManaged } from "../../interfaces/IManaged.sol"; import { GraphDirectory } from "../../GraphDirectory.sol"; +// TODO: create custom var-name-mixedcase +/* solhint-disable var-name-mixedcase */ + /** * @title Graph Managed contract * @dev The Managed contract provides an interface to interact with the Controller. @@ -19,7 +22,7 @@ abstract contract Managed is IManaged, GraphDirectory { /// Controller that manages this contract IController private __DEPRECATED_controller; /// @dev Cache for the addresses of the contracts retrieved from the controller - mapping(bytes32 => address) private __DEPRECATED_addressCache; + mapping(bytes32 contractName => address contractAddress) private __DEPRECATED_addressCache; /// @dev Gap for future storage variables uint256[10] private __gap; @@ -35,41 +38,6 @@ abstract contract Managed is IManaged, GraphDirectory { error ManagedSetControllerDeprecated(); - constructor(address _controller) GraphDirectory(_controller) {} - - function controller() public view override returns (IController) { - return IController(CONTROLLER); - } - - /** - * @dev Revert if the controller is paused or partially paused - */ - function _notPartialPaused() internal view { - require(!controller().paused(), "Paused"); - require(!controller().partialPaused(), "Partial-paused"); - } - - /** - * @dev Revert if the controller is paused - */ - function _notPaused() internal view virtual { - require(!controller().paused(), "Paused"); - } - - /** - * @dev Revert if the caller is not the governor - */ - function _onlyGovernor() internal view { - require(msg.sender == controller().getGovernor(), "Only Controller governor"); - } - - /** - * @dev Revert if the caller is not the Controller - */ - function _onlyController() internal view { - require(msg.sender == CONTROLLER, "Caller must be Controller"); - } - /** * @dev Revert if the controller is paused or partially paused */ @@ -102,10 +70,45 @@ abstract contract Managed is IManaged, GraphDirectory { _; } + constructor(address controller_) GraphDirectory(controller_) {} + /** * @notice Set Controller. Deprecated, will revert. */ function setController(address) external view override onlyController { revert ManagedSetControllerDeprecated(); } + + function controller() public view override returns (IController) { + return IController(CONTROLLER); + } + + /** + * @dev Revert if the controller is paused or partially paused + */ + function _notPartialPaused() internal view { + require(!controller().paused(), "Paused"); + require(!controller().partialPaused(), "Partial-paused"); + } + + /** + * @dev Revert if the controller is paused + */ + function _notPaused() internal view virtual { + require(!controller().paused(), "Paused"); + } + + /** + * @dev Revert if the caller is not the governor + */ + function _onlyGovernor() internal view { + require(msg.sender == controller().getGovernor(), "Only Controller governor"); + } + + /** + * @dev Revert if the caller is not the Controller + */ + function _onlyController() internal view { + require(msg.sender == CONTROLLER, "Caller must be Controller"); + } } diff --git a/packages/horizon/package.json b/packages/horizon/package.json index fff88b6d4..a39d4adc6 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -37,6 +37,7 @@ "prettier-plugin-solidity": "^1.3.1", "solhint": "^4.5.2", "solhint-graph-config": "workspace:^0.0.1", + "solhint-plugin-graph": "workspace:^0.0.1", "solidity-coverage": "^0.8.0", "ts-node": ">=8.0.0", "typechain": "^8.3.0", diff --git a/packages/solhint-graph-config/index.js b/packages/solhint-graph-config/index.js index f7193d748..f05ee0df6 100644 --- a/packages/solhint-graph-config/index.js +++ b/packages/solhint-graph-config/index.js @@ -24,5 +24,7 @@ module.exports = { // graph 'graph/leading-underscore': 'warn', + + 'gas-custom-errors': 'off' }, } diff --git a/packages/solhint-plugin-graph/index.js b/packages/solhint-plugin-graph/index.js index cd16840e8..d21c8840d 100644 --- a/packages/solhint-plugin-graph/index.js +++ b/packages/solhint-plugin-graph/index.js @@ -4,6 +4,8 @@ function hasLeadingUnderscore(text) { class Base { constructor(reporter, config, source, fileName) { + this.ignoreDeprecated = true; + this.deprecatedPrefix = '__DEPRECATED_'; this.reporter = reporter; this.ignored = this.constructor.global; this.ruleId = this.constructor.ruleId; @@ -68,6 +70,10 @@ module.exports = [ } validateName(node, type) { + if (this.ignoreDeprecated && node.name.startsWith(this.deprecatedPrefix)) { + return + } + const isPrivate = node.visibility === 'private' const isInternal = node.visibility === 'internal' || node.visibility === 'default' const isConstant = node.isDeclaredConst diff --git a/yarn.lock b/yarn.lock index c105ba53f..a164666c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2937,6 +2937,7 @@ __metadata: prettier-plugin-solidity: "npm:^1.3.1" solhint: "npm:^4.5.2" solhint-graph-config: "workspace:^0.0.1" + solhint-plugin-graph: "workspace:^0.0.1" solidity-coverage: "npm:^0.8.0" ts-node: "npm:>=8.0.0" typechain: "npm:^8.3.0" From fd8ad110eac8919a2f37e22090d392952c345d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 11:36:56 -0300 Subject: [PATCH 027/277] chore: staking interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../interfaces/IHorizonStakingExtension.sol | 20 ++++++------------- .../contracts/staking/HorizonStaking.sol | 3 ++- .../staking/HorizonStakingExtension.sol | 2 +- .../staking/HorizonStakingStorage.sol | 14 +++++++------ .../staking/StakingBackwardsCompatibility.sol | 14 ++++--------- 5 files changed, 21 insertions(+), 32 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol index 7c5da23e2..4e4811e3a 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol @@ -5,7 +5,7 @@ pragma abicoder v2; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; -interface IHorizonStakingExtension { +interface IHorizonStakingExtension is IHorizonStakingTypes { /** * @dev Emitted when an operator is allowed or denied by a service provider for a particular data service */ @@ -41,29 +41,21 @@ interface IHorizonStakingExtension { uint32 delegationRatio ) external view returns (uint256); - function getServiceProvider( - address serviceProvider - ) external view returns (IHorizonStakingTypes.ServiceProvider memory); + function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); function getMaxThawingPeriod() external view returns (uint64); - function getDelegationPool( - address serviceProvider, - address verifier - ) external view returns (IHorizonStakingTypes.DelegationPool memory); + function getDelegationPool(address serviceProvider, address verifier) external view returns (DelegationPool memory); function getDelegation( address delegator, address serviceProvider, address verifier - ) external view returns (IHorizonStakingTypes.Delegation memory); + ) external view returns (Delegation memory); - function getThawRequest(bytes32 thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory); + function getThawRequest(bytes32 thawRequestId) external view returns (ThawRequest memory); - function getProvision( - address serviceProvider, - address verifier - ) external view returns (IHorizonStakingTypes.Provision memory); + function getProvision(address serviceProvider, address verifier) external view returns (Provision memory); function getDelegationFeeCut( address serviceProvider, diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index a773d8dd0..9254587f9 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -9,6 +9,7 @@ import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; @@ -20,7 +21,7 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * It uses a HorizonStakingExtension contract to implement the full IHorizonStaking interface through delegatecalls. * This is due to the contract size limit on Arbitrum (24kB like mainnet). */ -contract HorizonStaking is HorizonStakingV1Storage, IHorizonStakingBase, GraphUpgradeable { +contract HorizonStaking is GraphUpgradeable, Multicall, HorizonStakingV1Storage, IHorizonStakingBase { /// @dev 100% in parts per million uint32 internal constant MAX_PPM = 1000000; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 12a685277..7e54fd361 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -16,7 +16,7 @@ import { StakingBackwardsCompatibility } from "./StakingBackwardsCompatibility.s * 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. */ -contract HorizonStakingExtension is StakingBackwardsCompatibility, IHorizonStakingExtension, IL2StakingBase { +contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBase, IHorizonStakingExtension { /// @dev Minimum amount of tokens that can be delegated uint256 private constant MINIMUM_DELEGATION = 1e18; diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index a640568ef..260e7ee65 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -15,7 +15,7 @@ import { Managed } from "./utilities/Managed.sol"; * @notice This contract holds all the storage variables for the Staking contract, version 1 */ // solhint-disable-next-line max-states-count -abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { +abstract contract HorizonStakingV1Storage is Managed { // -- Staking -- /// @dev Minimum amount of tokens an indexer needs to stake. @@ -53,7 +53,7 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { uint32 internal __DEPRECATED_alphaDenominator; /// @dev Service provider stakes : serviceProviderAddress => ServiceProvider - mapping(address serviceProvider => ServiceProviderInternal details) internal _serviceProviders; + mapping(address serviceProvider => IHorizonStakingTypes.ServiceProviderInternal details) internal _serviceProviders; /// @dev Allocations : allocationID => Allocation /// Deprecated, now applied on the SubgraphService @@ -94,7 +94,8 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { /// @dev Delegation pools : serviceProvider => DelegationPoolInternal /// These are for the subgraph data service. - mapping(address serviceProvider => DelegationPoolInternal delegationPool) internal _legacyDelegationPools; + mapping(address serviceProvider => IHorizonStakingTypes.DelegationPoolInternal delegationPool) + internal _legacyDelegationPools; // -- Operators -- @@ -124,7 +125,8 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { /// @dev Provisions from each service provider for each data service /// ServiceProvider => Verifier => Provision - mapping(address serviceProvider => mapping(address verifier => Provision provision)) internal _provisions; + mapping(address serviceProvider => mapping(address verifier => IHorizonStakingTypes.Provision provision)) + internal _provisions; /// @dev Delegation fee cuts for each service provider on each provision, by fee type: /// ServiceProvider => Verifier => Fee Type => Fee Cut. @@ -135,7 +137,7 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { mapping(address serviceProvider => mapping(address verifier => mapping(uint256 feeType => uint256 feeCut))) public delegationFeeCut; - mapping(bytes32 thawRequestId => ThawRequest thawRequest) internal _thawRequests; + mapping(bytes32 thawRequestId => IHorizonStakingTypes.ThawRequest thawRequest) internal _thawRequests; // indexer => verifier => operator => authorized mapping(address serviceProvider => mapping(address verifier => mapping(address operator => bool authorized))) @@ -145,7 +147,7 @@ abstract contract HorizonStakingV1Storage is Managed, IHorizonStakingTypes { bool public delegationSlashingEnabled; // delegation pools for each service provider and verifier - mapping(address serviceProvider => mapping(address verifier => DelegationPoolInternal delegationPool)) + mapping(address serviceProvider => mapping(address verifier => IHorizonStakingTypes.DelegationPoolInternal delegationPool)) internal _delegationPools; // allowed verifiers for locked provisions (i.e. from GraphTokenLockWallets) diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index ea51f372c..09e4d114a 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -7,13 +7,12 @@ import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRew import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; +import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; import { ExponentialRebates } from "./libraries/ExponentialRebates.sol"; -import { Multicall } from "@graphprotocol/contracts/contracts/base/Multicall.sol"; -import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; @@ -27,12 +26,7 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * Note that this contract delegates part of its functionality to a StakingExtension contract. * This is due to the 24kB contract size limit on Ethereum. */ -abstract contract StakingBackwardsCompatibility is - HorizonStakingV1Storage, - GraphUpgradeable, - Multicall, - IStakingBackwardsCompatibility -{ +abstract contract StakingBackwardsCompatibility is HorizonStakingV1Storage, IStakingBackwardsCompatibility { /// @dev 100% in parts per million uint32 internal constant MAX_PPM = 1000000; @@ -415,7 +409,7 @@ abstract contract StakingBackwardsCompatibility is */ function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; - DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; + IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; if (pool.tokens > 0 && pool.__DEPRECATED_queryFeeCut < MAX_PPM) { uint256 indexerCut = (uint256(pool.__DEPRECATED_queryFeeCut) * _tokens) / MAX_PPM; delegationRewards = _tokens - indexerCut; @@ -433,7 +427,7 @@ abstract contract StakingBackwardsCompatibility is */ function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; - DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; + IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; if (pool.tokens > 0 && pool.__DEPRECATED_indexingRewardCut < MAX_PPM) { uint256 indexerCut = (uint256(pool.__DEPRECATED_indexingRewardCut) * _tokens) / MAX_PPM; delegationRewards = _tokens - indexerCut; From 5e12031e1bd05ce5450249f096643404866b607d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 12:00:18 -0300 Subject: [PATCH 028/277] chore(staking): move managed to main contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/contracts/staking/HorizonStaking.sol | 2 +- packages/horizon/contracts/staking/HorizonStakingStorage.sol | 4 +--- packages/horizon/hardhat.config.ts | 2 ++ packages/horizon/package.json | 1 + yarn.lock | 1 + 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 9254587f9..0f5773d6e 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -21,7 +21,7 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * It uses a HorizonStakingExtension contract to implement the full IHorizonStaking interface through delegatecalls. * This is due to the contract size limit on Arbitrum (24kB like mainnet). */ -contract HorizonStaking is GraphUpgradeable, Multicall, HorizonStakingV1Storage, IHorizonStakingBase { +contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV1Storage, IHorizonStakingBase { /// @dev 100% in parts per million uint32 internal constant MAX_PPM = 1000000; diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 260e7ee65..e23cde9c7 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -5,8 +5,6 @@ pragma solidity 0.8.24; import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; -import { Managed } from "./utilities/Managed.sol"; - // TODO: create custom var-name-mixedcase /* solhint-disable var-name-mixedcase */ @@ -15,7 +13,7 @@ import { Managed } from "./utilities/Managed.sol"; * @notice This contract holds all the storage variables for the Staking contract, version 1 */ // solhint-disable-next-line max-states-count -abstract contract HorizonStakingV1Storage is Managed { +abstract contract HorizonStakingV1Storage { // -- Staking -- /// @dev Minimum amount of tokens an indexer needs to stake. diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index 123791c44..f4efae525 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -1,5 +1,7 @@ // import '@nomicfoundation/hardhat-foundry' import '@nomicfoundation/hardhat-toolbox' +import 'hardhat-storage-layout' + import { HardhatUserConfig } from 'hardhat/config' const config: HardhatUserConfig = { diff --git a/packages/horizon/package.json b/packages/horizon/package.json index a39d4adc6..cdcfa441b 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -32,6 +32,7 @@ "ethers": "^6.4.0", "hardhat": "^2.20.1", "hardhat-gas-reporter": "^1.0.8", + "hardhat-storage-layout": "^0.1.7", "lint-staged": "^15.2.2", "prettier": "^3.2.5", "prettier-plugin-solidity": "^1.3.1", diff --git a/yarn.lock b/yarn.lock index a164666c1..1258d7100 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2932,6 +2932,7 @@ __metadata: ethers: "npm:^6.4.0" hardhat: "npm:^2.20.1" hardhat-gas-reporter: "npm:^1.0.8" + hardhat-storage-layout: "npm:^0.1.7" lint-staged: "npm:^15.2.2" prettier: "npm:^3.2.5" prettier-plugin-solidity: "npm:^1.3.1" From 5d1f32774320de81cfaf283b1922ce38adfde476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 12:21:07 -0300 Subject: [PATCH 029/277] chore: simplify Managed contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../staking/StakingBackwardsCompatibility.sol | 2 +- .../contracts/staking/utilities/Managed.sol | 43 +++---------------- 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 09e4d114a..79a97b341 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -26,7 +26,7 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * Note that this contract delegates part of its functionality to a StakingExtension contract. * This is due to the 24kB contract size limit on Ethereum. */ -abstract contract StakingBackwardsCompatibility is HorizonStakingV1Storage, IStakingBackwardsCompatibility { +abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Storage, IStakingBackwardsCompatibility { /// @dev 100% in parts per million uint32 internal constant MAX_PPM = 1000000; diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index 496caca0e..8cfadfb6d 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -30,11 +30,6 @@ abstract contract Managed is IManaged, GraphDirectory { /// Emitted when a contract parameter has been updated event ParameterUpdated(string param); - /// (Deprecated) Emitted when the controller address has been set - event SetController(address controller); - - ///(Deprecated) Emitted when contract with `nameHash` is synced to `contractAddress`. - event ContractSynced(bytes32 indexed nameHash, address contractAddress); error ManagedSetControllerDeprecated(); @@ -42,7 +37,8 @@ abstract contract Managed is IManaged, GraphDirectory { * @dev Revert if the controller is paused or partially paused */ modifier notPartialPaused() { - _notPartialPaused(); + require(!controller().paused(), "Paused"); + require(!controller().partialPaused(), "Partial-paused"); _; } @@ -50,7 +46,7 @@ abstract contract Managed is IManaged, GraphDirectory { * @dev Revert if the controller is paused */ modifier notPaused() { - _notPaused(); + require(!controller().paused(), "Paused"); _; } @@ -58,7 +54,7 @@ abstract contract Managed is IManaged, GraphDirectory { * @dev Revert if the caller is not the Controller */ modifier onlyController() { - _onlyController(); + require(msg.sender == CONTROLLER, "Caller must be Controller"); _; } @@ -66,7 +62,7 @@ abstract contract Managed is IManaged, GraphDirectory { * @dev Revert if the caller is not the governor */ modifier onlyGovernor() { - _onlyGovernor(); + require(msg.sender == controller().getGovernor(), "Only Controller governor"); _; } @@ -82,33 +78,4 @@ abstract contract Managed is IManaged, GraphDirectory { function controller() public view override returns (IController) { return IController(CONTROLLER); } - - /** - * @dev Revert if the controller is paused or partially paused - */ - function _notPartialPaused() internal view { - require(!controller().paused(), "Paused"); - require(!controller().partialPaused(), "Partial-paused"); - } - - /** - * @dev Revert if the controller is paused - */ - function _notPaused() internal view virtual { - require(!controller().paused(), "Paused"); - } - - /** - * @dev Revert if the caller is not the governor - */ - function _onlyGovernor() internal view { - require(msg.sender == controller().getGovernor(), "Only Controller governor"); - } - - /** - * @dev Revert if the caller is not the Controller - */ - function _onlyController() internal view { - require(msg.sender == CONTROLLER, "Caller must be Controller"); - } } From 896e3f515e45f58da359076d57aeb384d99edf09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 14:43:42 -0300 Subject: [PATCH 030/277] feat(directory): improve graph directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/arbitrum/ITokenGateway.sol | 27 ++-- packages/contracts/package.json | 1 + packages/horizon/contracts/GraphDirectory.sol | 38 ------ .../contracts/data-service/GraphDirectory.sol | 127 ++++++++++++++---- .../extensions/DataServiceFees.sol | 2 +- .../extensions/DataServiceRescuable.sol | 2 +- .../utilities/ProvisionManager.sol | 6 +- .../horizon/contracts/escrow/GraphEscrow.sol | 20 +-- .../horizon/contracts/interfaces/IManaged.sol | 25 ---- .../contracts/payments/GraphPayments.sol | 24 ++-- .../contracts/staking/HorizonStaking.sol | 22 ++- .../staking/HorizonStakingExtension.sol | 2 +- .../staking/StakingBackwardsCompatibility.sol | 49 ++----- .../contracts/staking/utilities/Managed.sol | 32 ++--- .../test/deployments/Deployments.t.sol | 10 +- .../contracts/DisputeManager.sol | 32 ++--- .../contracts/SubgraphService.sol | 12 +- .../contracts/utilities/AllocationManager.sol | 24 ++-- yarn.lock | 1 + 19 files changed, 214 insertions(+), 242 deletions(-) delete mode 100644 packages/horizon/contracts/GraphDirectory.sol delete mode 100644 packages/horizon/contracts/interfaces/IManaged.sol diff --git a/packages/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/contracts/contracts/arbitrum/ITokenGateway.sol index 977fe07f2..41b11f7fc 100644 --- a/packages/contracts/contracts/arbitrum/ITokenGateway.sol +++ b/packages/contracts/contracts/arbitrum/ITokenGateway.sol @@ -23,7 +23,7 @@ * */ -pragma solidity ^0.7.6; +pragma solidity ^0.7.6 || 0.8.24; interface ITokenGateway { /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated @@ -47,21 +47,20 @@ interface ITokenGateway { // ); function outboundTransfer( - address _token, - address _to, - uint256 _amount, - uint256 _maxGas, - uint256 _gasPriceBid, - bytes calldata _data - ) external payable returns (bytes memory); + address oken, + address t, + uint256 amunt, + uint256 maxas, + uint256 gasPiceBid, + bytes calldata data + ) external payable returns (bytes memory); function finalizeInboundTransfer( - address _token, - address _from, - address _to, - uint256 _amount, - bytes calldata _data - ) external payable; + address token, address from, + address to, + uint256 amount, + bytes calldata data + )external payable; /** * @notice Calculate the address used when bridging an ERC20 token diff --git a/packages/contracts/package.json b/packages/contracts/package.json index e3f8b71c8..0f112bcc1 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -73,6 +73,7 @@ "prettier-plugin-solidity": "^1.3.1", "solhint": "^4.1.1", "solhint-graph-config": "workspace:^0.0.1", + "solhint-plugin-graph": "workspace:^0.0.1", "solidity-coverage": "^0.7.16", "ts-node": "^10.9.1", "typechain": "^5.0.0", diff --git a/packages/horizon/contracts/GraphDirectory.sol b/packages/horizon/contracts/GraphDirectory.sol deleted file mode 100644 index f36b0f9b3..000000000 --- a/packages/horizon/contracts/GraphDirectory.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity 0.8.24; - -import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; - -/** - * @title GraphDirectory contract - * @notice This contract is meant to be inherited by other contracts that - * need to keep track of the addresses of the core Graph Horizon contracts. - * It fetches the addresses from the Controller supplied during construction, - * and uses immutable variables to minimize gas costs. - */ -contract GraphDirectory { - address public immutable CONTROLLER; - address public immutable STAKING; - address public immutable EPOCH_MANAGER; - address public immutable GRAPH_TOKEN; - address public immutable GRAPH_TOKEN_GATEWAY; - // TODO: also GraphPayments and ScalarEscrow? - // Legacy contracts (pre-Horizon) used for StakingBackwardCompatibility - address public immutable REWARDS_MANAGER; - address public immutable CURATION; - address public immutable GRAPH_PAYMENTS; - address public immutable GRAPH_ESCROW; - - constructor(address controller) { - CONTROLLER = controller; - STAKING = IController(controller).getContractProxy(keccak256("Staking")); - EPOCH_MANAGER = IController(controller).getContractProxy(keccak256("EpochManager")); - GRAPH_TOKEN = IController(controller).getContractProxy(keccak256("GraphToken")); - GRAPH_TOKEN_GATEWAY = IController(controller).getContractProxy(keccak256("GraphTokenGateway")); - REWARDS_MANAGER = IController(controller).getContractProxy(keccak256("RewardsManager")); - CURATION = IController(controller).getContractProxy(keccak256("Curation")); - GRAPH_PAYMENTS = IController(controller).getContractProxy(keccak256("GraphPayments")); - GRAPH_ESCROW = IController(controller).getContractProxy(keccak256("GraphEscrow")); - } -} diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index b79d7de52..d76bda88f 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -3,53 +3,122 @@ pragma solidity 0.8.24; import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; +import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; -// import { IGraphTokenGateway } from "@graphprotocol/contracts/contracts/gateway/IGraphTokenGateway.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; -import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; -import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; +import { ITokenGateway } from "@graphprotocol/contracts/contracts/arbitrum/ITokenGateway.sol"; +/** + * @title GraphDirectory contract + * @notice This contract is meant to be inherited by other contracts that + * need to keep track of the addresses of the core Graph Horizon contracts. + * It fetches the addresses from the Controller supplied during construction, + * and uses immutable variables to minimize gas costs. + */ abstract contract GraphDirectory { - IController public immutable GRAPH_CONTROLLER; - IHorizonStaking public immutable GRAPH_STAKING; - IEpochManager public immutable GRAPH_EPOCH_MANAGER; - IGraphToken public immutable GRAPH_TOKEN; - // IGraphTokenGateway public immutable graphTokenGateway; - IGraphEscrow public immutable GRAPH_ESCROW; - IGraphPayments public immutable GRAPH_PAYMENTS; - IRewardsManager public immutable GRAPH_REWARDS_MANAGER; + IController private immutable GRAPH_CONTROLLER; + + // Graph Horizon contracts + IGraphToken private immutable GRAPH_TOKEN; + IHorizonStaking private immutable GRAPH_STAKING; + IGraphPayments private immutable GRAPH_PAYMENTS; + IGraphEscrow private immutable GRAPH_ESCROW; + + // Legacy Graph contracts + // Required for StakingBackwardCompatibility + // TODO: remove these once StakingBackwardCompatibility is removed + IEpochManager private immutable GRAPH_EPOCH_MANAGER; + IRewardsManager private immutable GRAPH_REWARDS_MANAGER; + ICuration private immutable GRAPH_CURATION; + ITokenGateway private immutable GRAPH_TOKEN_GATEWAY; event GraphDirectoryInitialized( IController graphController, - IHorizonStaking graphStaking, - IEpochManager graphEpochManager, IGraphToken graphToken, - // address graphTokenGateway, - IGraphEscrow graphEscrow, + IHorizonStaking graphStaking, IGraphPayments graphPayments, - IRewardsManager graphRewardsManager + IGraphEscrow graphEscrow, + IEpochManager graphEpochManager, + IRewardsManager graphRewardsManager, + ICuration graphCuration, + ITokenGateway graphTokenGateway ); + error GraphDirectoryInvalidZeroAddress(); + constructor(address controller) { + if (controller == address(0)) { + revert GraphDirectoryInvalidZeroAddress(); + } GRAPH_CONTROLLER = IController(controller); - GRAPH_STAKING = IHorizonStaking(GRAPH_CONTROLLER.getContractProxy(keccak256("Staking"))); - GRAPH_EPOCH_MANAGER = IEpochManager(GRAPH_CONTROLLER.getContractProxy(keccak256("EpochManager"))); - GRAPH_TOKEN = IGraphToken(GRAPH_CONTROLLER.getContractProxy(keccak256("GraphToken"))); - // graphTokenGateway = graphController.getContractProxy(keccak256("GraphTokenGateway")); - GRAPH_ESCROW = IGraphEscrow(GRAPH_CONTROLLER.getContractProxy(keccak256("GraphEscrow"))); - GRAPH_PAYMENTS = IGraphPayments(GRAPH_CONTROLLER.getContractProxy(keccak256("GraphPayments"))); - GRAPH_REWARDS_MANAGER = IRewardsManager(GRAPH_CONTROLLER.getContractProxy(keccak256("RewardsManager"))); + + GRAPH_TOKEN = IGraphToken(_getContractFromController("GraphToken")); + GRAPH_STAKING = IHorizonStaking(_getContractFromController("Staking")); + GRAPH_PAYMENTS = IGraphPayments(_getContractFromController("GraphPayments")); + GRAPH_ESCROW = IGraphEscrow(_getContractFromController("GraphEscrow")); + GRAPH_EPOCH_MANAGER = IEpochManager(_getContractFromController("EpochManager")); + GRAPH_REWARDS_MANAGER = IRewardsManager(_getContractFromController("RewardsManager")); + GRAPH_CURATION = ICuration(_getContractFromController("Curation")); + GRAPH_TOKEN_GATEWAY = ITokenGateway(_getContractFromController("GraphTokenGateway")); + emit GraphDirectoryInitialized( GRAPH_CONTROLLER, - GRAPH_STAKING, - GRAPH_EPOCH_MANAGER, GRAPH_TOKEN, - // graphTokenGateway, - GRAPH_ESCROW, + GRAPH_STAKING, GRAPH_PAYMENTS, - GRAPH_REWARDS_MANAGER + GRAPH_ESCROW, + GRAPH_EPOCH_MANAGER, + GRAPH_REWARDS_MANAGER, + GRAPH_CURATION, + GRAPH_TOKEN_GATEWAY ); } + + function _graphController() internal view returns (IController) { + return GRAPH_CONTROLLER; + } + + function _graphToken() internal view returns (IGraphToken) { + return GRAPH_TOKEN; + } + + function _graphStaking() internal view returns (IHorizonStaking) { + return GRAPH_STAKING; + } + + function _graphPayments() internal view returns (IGraphPayments) { + return GRAPH_PAYMENTS; + } + + function _graphEscrow() internal view returns (IGraphEscrow) { + return GRAPH_ESCROW; + } + + function _graphEpochManager() internal view returns (IEpochManager) { + return GRAPH_EPOCH_MANAGER; + } + + function _graphRewardsManager() internal view returns (IRewardsManager) { + return GRAPH_REWARDS_MANAGER; + } + + function _graphCuration() internal view returns (ICuration) { + return GRAPH_CURATION; + } + + function _graphTokenGateway() internal view returns (ITokenGateway) { + return GRAPH_TOKEN_GATEWAY; + } + + function _getContractFromController(bytes memory __contractName) private view returns (address) { + address contractAddress = GRAPH_CONTROLLER.getContractProxy(keccak256(contractName)); + if (contractAddress == address(0)) { + revert GraphDirectoryInvalidZeroAddress(); + } + return contractAddress; + } } diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 3978d9a48..b803c9248 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -66,7 +66,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat uint256 _tokens, uint256 _unlockTimestamp ) internal { - feesProvisionTracker[_feeType].lock(GRAPH_STAKING, _serviceProvider, _tokens, delegationRatio); + feesProvisionTracker[_feeType].lock(_graphStaking(), _serviceProvider, _tokens, delegationRatio); StakeClaimsList storage claimsList = claimsLists[_feeType][_serviceProvider]; bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 76a25162a..b345a8683 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -35,7 +35,7 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { } function rescueGRT(address to, uint256 amount) external onlyRescuer { - _rescueTokens(to, address(GRAPH_TOKEN), amount); + _rescueTokens(to, address(_graphToken()), amount); } function rescueETH(address payable to, uint256 amount) external onlyRescuer { diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index dd9d2677f..946db4b0f 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -31,7 +31,7 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage error ProvisionManagerNotAuthorized(address caller, address serviceProvider, address service); modifier onlyProvisionAuthorized(address serviceProvider) { - if (!GRAPH_STAKING.isAuthorized(msg.sender, serviceProvider, address(this))) { + if (!_graphStaking().isAuthorized(msg.sender, serviceProvider, address(this))) { revert ProvisionManagerNotAuthorized(msg.sender, serviceProvider, address(this)); } _; @@ -50,7 +50,7 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage function _checkAndAcceptProvision(address _serviceProvider) internal virtual { _checkProvisionParameters(_serviceProvider); - GRAPH_STAKING.acceptProvisionParameters(_serviceProvider); + _graphStaking().acceptProvisionParameters(_serviceProvider); } // -- Provision Parameters: setters -- @@ -104,6 +104,6 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage } function _getProvision(address _serviceProvider) internal view returns (IHorizonStaking.Provision memory) { - return GRAPH_STAKING.get(_serviceProvider); + return _graphStaking().get(_serviceProvider); } } diff --git a/packages/horizon/contracts/escrow/GraphEscrow.sol b/packages/horizon/contracts/escrow/GraphEscrow.sol index 6e6921a82..e6d021425 100644 --- a/packages/horizon/contracts/escrow/GraphEscrow.sol +++ b/packages/horizon/contracts/escrow/GraphEscrow.sol @@ -4,11 +4,15 @@ pragma solidity ^0.8.24; import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; -import { GraphDirectory } from "../GraphDirectory.sol"; -import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; + import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; + contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirectory { + using TokenUtils for IGraphToken; + // -- Events -- event AuthorizedCollector(address indexed sender, address indexed dataService); @@ -102,7 +106,7 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector // Deposit funds into the escrow for a receiver function deposit(address receiver, uint256 amount) external { escrowAccounts[msg.sender][receiver].balance += amount; - TokenUtils.pullTokens(IGraphToken(GRAPH_TOKEN), msg.sender, amount); + _graphToken().pullTokens(msg.sender, amount); emit Deposit(msg.sender, receiver, amount); } @@ -122,7 +126,7 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector emit Deposit(msg.sender, receiver, amount); } - TokenUtils.pullTokens(IGraphToken(GRAPH_TOKEN), msg.sender, totalAmount); + _graphToken().pullTokens(msg.sender, totalAmount); } // Requests to thaw a specific amount of escrow from a receiver's escrow account @@ -174,7 +178,7 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector account.balance -= amount; // Reduce the balance by the withdrawn amount (no underflow risk) account.amountThawing = 0; account.thawEndTimestamp = 0; - TokenUtils.pushTokens(IGraphToken(GRAPH_TOKEN), msg.sender, amount); + _graphToken().pushTokens(msg.sender, amount); emit Withdraw(msg.sender, receiver, amount); } @@ -212,10 +216,8 @@ contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirector emit Collect(sender, receiver, amount); // Approve tokens so GraphPayments can pull them - IGraphToken graphToken = IGraphToken(GRAPH_TOKEN); - IGraphPayments graphPayments = IGraphPayments(GRAPH_PAYMENTS); - graphToken.approve(address(graphPayments), amount); - graphPayments.collect(receiver, dataService, amount, paymentType, tokensDataService); + _graphToken().approve(address(_graphPayments()), amount); + _graphPayments().collect(receiver, dataService, amount, paymentType, tokensDataService); } // Get the balance of a sender-receiver pair diff --git a/packages/horizon/contracts/interfaces/IManaged.sol b/packages/horizon/contracts/interfaces/IManaged.sol deleted file mode 100644 index 13c129b2f..000000000 --- a/packages/horizon/contracts/interfaces/IManaged.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.6.12 <0.9.0; -pragma abicoder v2; - -import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; - -/** - * @title Managed Interface - * @dev Interface for contracts that can be managed by a controller. - */ -interface IManaged { - /** - * @notice (Deprecated) Set the controller that manages this contract - * @dev Only the current controller can set a new controller - * @param controller Address of the new controller - */ - function setController(address controller) external; - - /** - * @notice Get the Controller that manages this contract - * @return The Controller as an IController interface - */ - function controller() external view returns (IController); -} diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 41ba9f063..f5e0d2031 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -4,11 +4,15 @@ pragma solidity ^0.8.24; import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; -import { GraphDirectory } from "../GraphDirectory.sol"; -import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; + import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; + contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { + using TokenUtils for IGraphToken; + uint256 private immutable MAX_PPM = 1000000; // 100% in parts per million // -- Errors -- @@ -26,7 +30,7 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi // -- Constructor -- constructor(address controller, uint256 protocolPaymentCut) GraphDirectory(controller) { - protocolPaymentCut = protocolPaymentCut; + PROTOCOL_PAYMENT_CUT = protocolPaymentCut; } // collect funds from a sender, pay cuts and forward the rest to the receiver @@ -37,24 +41,22 @@ contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDi IGraphPayments.PaymentTypes paymentType, uint256 tokensDataService ) external { - IGraphToken graphToken = IGraphToken(GRAPH_TOKEN); - IHorizonStaking staking = IHorizonStaking(STAKING); - TokenUtils.pullTokens(graphToken, msg.sender, amount); + _graphToken().pullTokens(msg.sender, amount); // Pay protocol cut uint256 tokensProtocol = (amount * PROTOCOL_PAYMENT_CUT) / MAX_PPM; - TokenUtils.burnTokens(graphToken, tokensProtocol); + _graphToken().burnTokens(tokensProtocol); // Pay data service cut - TokenUtils.pushTokens(graphToken, dataService, tokensDataService); + _graphToken().pushTokens(dataService, tokensDataService); // Get delegation cut - uint256 delegationFeeCut = staking.getDelegationFeeCut(receiver, dataService, uint8(paymentType)); + uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, uint8(paymentType)); uint256 tokensDelegationPool = (amount * delegationFeeCut) / MAX_PPM; - staking.addToDelegationPool(receiver, dataService, tokensDelegationPool); + _graphStaking().addToDelegationPool(receiver, dataService, tokensDelegationPool); // Pay the rest to the receiver uint256 tokensReceiver = amount - tokensProtocol - tokensDataService - tokensDelegationPool; - TokenUtils.pushTokens(graphToken, receiver, tokensReceiver); + _graphToken().pushTokens(receiver, tokensReceiver); } } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 0f5773d6e..77812d5b3 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -22,6 +22,8 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * This is due to the contract size limit on Arbitrum (24kB like mainnet). */ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV1Storage, IHorizonStakingBase { + using TokenUtils for IGraphToken; + /// @dev 100% in parts per million uint32 internal constant MAX_PPM = 1000000; @@ -341,7 +343,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV uint256 lockingPeriod = __DEPRECATED_thawingPeriod; if (lockingPeriod == 0) { sp.tokensStaked = stakedTokens - tokens; - TokenUtils.pushTokens(_graphToken(), serviceProvider, tokens); + _graphToken().pushTokens(serviceProvider, tokens); emit StakeWithdrawn(serviceProvider, tokens); } else { // Before locking more tokens, withdraw any unlocked ones if possible @@ -393,10 +395,10 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV if (providerTokensSlashed > 0) { require((prov.tokens * prov.maxVerifierCut) / MAX_PPM >= verifierCutAmount, "verifier cut too high"); if (verifierCutAmount > 0) { - TokenUtils.pushTokens(_graphToken(), verifierCutDestination, verifierCutAmount); + _graphToken().pushTokens(verifierCutDestination, verifierCutAmount); emit VerifierCutSent(serviceProvider, verifier, verifierCutDestination, verifierCutAmount); } - TokenUtils.burnTokens(_graphToken(), providerTokensSlashed - verifierCutAmount); + _graphToken().burnTokens(providerTokensSlashed - verifierCutAmount); uint256 provisionFractionSlashed = (providerTokensSlashed * FIXED_POINT_PRECISION) / prov.tokens; // TODO check for rounding issues prov.tokensThawing = @@ -422,7 +424,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV } if (delegationSlashingEnabled) { require(pool.tokens >= tokensToSlash, "insufficient delegated tokens"); - TokenUtils.burnTokens(_graphToken(), tokensToSlash); + _graphToken().burnTokens(tokensToSlash); uint256 delegationFractionSlashed = (tokensToSlash * FIXED_POINT_PRECISION) / pool.tokens; pool.tokens = pool.tokens - tokensToSlash; pool.tokensThawing = @@ -541,7 +543,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV } // Transfer tokens to stake from caller to this contract - TokenUtils.pullTokens(_graphToken(), msg.sender, tokens); + _graphToken().pullTokens(msg.sender, tokens); // Stake the transferred tokens _stake(serviceProvider, tokens); @@ -554,7 +556,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV uint256 minSharesOut ) public override notPartialPaused { // Transfer tokens to stake from caller to this contract - TokenUtils.pullTokens(_graphToken(), msg.sender, tokens); + _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, verifier, tokens, minSharesOut); } @@ -652,7 +654,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV if (newServiceProvider != address(0)) { _delegate(newServiceProvider, verifier, thawedTokens, minSharesForNewProvider); } else { - TokenUtils.pushTokens(_graphToken(), msg.sender, thawedTokens); + _graphToken().pushTokens(msg.sender, thawedTokens); } emit DelegatedTokensWithdrawn(serviceProvider, verifier, msg.sender, thawedTokens); } @@ -836,10 +838,6 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV emit StakeDeposited(_serviceProvider, _tokens); } - function _graphToken() internal view returns (IGraphToken) { - return IGraphToken(GRAPH_TOKEN); - } - /** * @dev Withdraw indexer tokens once the thawing period has passed. * @param _indexer Address of indexer to withdraw funds from @@ -858,7 +856,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; // Return tokens to the indexer - TokenUtils.pushTokens(_graphToken(), _indexer, tokensToWithdraw); + _graphToken().pushTokens(_indexer, tokensToWithdraw); emit StakeWithdrawn(_indexer, tokensToWithdraw); } diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 7e54fd361..469e4cf3f 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -24,7 +24,7 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas * @dev Checks that the sender is the L2GraphTokenGateway as configured on the Controller. */ modifier onlyL2Gateway() { - require(msg.sender == GRAPH_TOKEN_GATEWAY, "ONLY_GATEWAY"); + require(msg.sender == address(_graphTokenGateway()), "ONLY_GATEWAY"); _; } diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 79a97b341..30a667b77 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -27,6 +27,8 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * This is due to the 24kB contract size limit on Ethereum. */ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Storage, IStakingBackwardsCompatibility { + using TokenUtils for IGraphToken; + /// @dev 100% in parts per million uint32 internal constant MAX_PPM = 1000000; @@ -96,7 +98,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor { // -- Pull tokens from the sender -- IGraphToken graphToken = _graphToken(); - TokenUtils.pullTokens(graphToken, msg.sender, queryFees); + _graphToken().pullTokens(msg.sender, queryFees); // -- Collect protocol tax -- protocolTax = _collectTax(queryFees, __DEPRECATED_protocolPercentage); @@ -135,7 +137,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor queryRebates = MathUtils.min(queryRebates, queryFees); // -- Burn rebates remanent -- - TokenUtils.burnTokens(graphToken, queryFees - queryRebates); + _graphToken().burnTokens(queryFees - queryRebates); // -- Distribute rebates -- if (queryRebates > 0) { @@ -155,7 +157,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor alloc.indexer, subgraphDeploymentID, allocationID, - _epochManager().currentEpoch(), + _graphEpochManager().currentEpoch(), tokens, protocolTax, curationFees, @@ -246,22 +248,6 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor emit StakeDeposited(_serviceProvider, _tokens); } - function _graphToken() internal view returns (IGraphToken) { - return IGraphToken(GRAPH_TOKEN); - } - - function _curation() internal view returns (ICuration) { - return ICuration(CURATION); - } - - function _rewardsManager() internal view returns (IRewardsManager) { - return IRewardsManager(REWARDS_MANAGER); - } - - function _epochManager() internal view returns (IEpochManager) { - return IEpochManager(EPOCH_MANAGER); - } - /** * @dev Collect tax to burn for an amount of tokens. * @param _tokens Total tokens received used to calculate the amount of tax to collect @@ -273,7 +259,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor // to prevent the tax from rounding down to zero uint256 tokensAfterTax = ((uint256(MAX_PPM) - _percentage) * _tokens) / MAX_PPM; uint256 tax = _tokens - tokensAfterTax; - TokenUtils.burnTokens(_graphToken(), tax); // Burn tax if any + _graphToken().burnTokens(tax); // Burn tax if any return tax; } @@ -283,11 +269,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor * @return Accumulated rewards per allocated token for the subgraph deployment */ function _updateRewards(bytes32 _subgraphDeploymentID) private returns (uint256) { - IRewardsManager rewardsManager = _rewardsManager(); - if (address(rewardsManager) == address(0)) { - return 0; - } - return rewardsManager.onSubgraphAllocationUpdate(_subgraphDeploymentID); + return _graphRewardsManager().onSubgraphAllocationUpdate(_subgraphDeploymentID); } /** @@ -296,15 +278,10 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor * @param _indexer Address of the indexer that did the allocation */ function _distributeRewards(address _allocationID, address _indexer) private { - IRewardsManager rewardsManager = _rewardsManager(); - if (address(rewardsManager) == address(0)) { - return; - } - // Automatically triggers update of rewards snapshot as allocation will change // after this call. Take rewards mint tokens for the Staking contract to distribute // between indexer and delegators - uint256 totalRewards = rewardsManager.takeRewards(_allocationID); + uint256 totalRewards = _graphRewardsManager().takeRewards(_allocationID); if (totalRewards == 0) { return; } @@ -332,7 +309,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor } else { // Transfer funds to the beneficiary's designated rewards destination if set address destination = __DEPRECATED_rewardsDestination[_beneficiary]; - TokenUtils.pushTokens(_graphToken(), destination == address(0) ? _beneficiary : destination, _amount); + _graphToken().pushTokens(destination == address(0) ? _beneficiary : destination, _amount); } } @@ -350,7 +327,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor Allocation memory alloc = __DEPRECATED_allocations[_allocationID]; // Validate that an allocation cannot be closed before one epoch - alloc.closedAtEpoch = _epochManager().currentEpoch(); + alloc.closedAtEpoch = _graphEpochManager().currentEpoch(); uint256 epochs = MathUtils.diffOrZero(alloc.closedAtEpoch, alloc.createdAtEpoch); // Indexer or operator can close an allocation @@ -453,7 +430,7 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor return 0; } - ICuration curation = _curation(); + ICuration curation = _graphCuration(); bool isCurationEnabled = _curationPercentage > 0 && address(curation) != address(0); if (isCurationEnabled && curation.isCurated(_subgraphDeploymentID)) { @@ -465,8 +442,8 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor // Transfer and call collect() // This function transfer tokens to a trusted protocol contracts // Then we call collect() to do the transfer bookeeping - _rewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); - TokenUtils.pushTokens(_graphToken(), address(curation), curationFees); + _graphRewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); + _graphToken().pushTokens(address(curation), curationFees); curation.collect(_subgraphDeploymentID, curationFees); } return curationFees; diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index 8cfadfb6d..459d807b5 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -2,10 +2,7 @@ pragma solidity 0.8.24; -import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; -import { IManaged } from "../../interfaces/IManaged.sol"; - -import { GraphDirectory } from "../../GraphDirectory.sol"; +import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; // TODO: create custom var-name-mixedcase /* solhint-disable var-name-mixedcase */ @@ -16,11 +13,11 @@ import { GraphDirectory } from "../../GraphDirectory.sol"; * Inspired by Livepeer: * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol */ -abstract contract Managed is IManaged, GraphDirectory { +abstract contract Managed is GraphDirectory { // -- State -- /// Controller that manages this contract - IController private __DEPRECATED_controller; + address private __DEPRECATED_controller; /// @dev Cache for the addresses of the contracts retrieved from the controller mapping(bytes32 contractName => address contractAddress) private __DEPRECATED_addressCache; /// @dev Gap for future storage variables @@ -31,14 +28,12 @@ abstract contract Managed is IManaged, GraphDirectory { /// Emitted when a contract parameter has been updated event ParameterUpdated(string param); - error ManagedSetControllerDeprecated(); - /** * @dev Revert if the controller is paused or partially paused */ modifier notPartialPaused() { - require(!controller().paused(), "Paused"); - require(!controller().partialPaused(), "Partial-paused"); + require(!_graphController().paused(), "Paused"); + require(!_graphController().partialPaused(), "Partial-paused"); _; } @@ -46,7 +41,7 @@ abstract contract Managed is IManaged, GraphDirectory { * @dev Revert if the controller is paused */ modifier notPaused() { - require(!controller().paused(), "Paused"); + require(!_graphController().paused(), "Paused"); _; } @@ -54,7 +49,7 @@ abstract contract Managed is IManaged, GraphDirectory { * @dev Revert if the caller is not the Controller */ modifier onlyController() { - require(msg.sender == CONTROLLER, "Caller must be Controller"); + require(msg.sender == address(_graphController()), "Caller must be Controller"); _; } @@ -62,20 +57,9 @@ abstract contract Managed is IManaged, GraphDirectory { * @dev Revert if the caller is not the governor */ modifier onlyGovernor() { - require(msg.sender == controller().getGovernor(), "Only Controller governor"); + require(msg.sender == _graphController().getGovernor(), "Only Controller governor"); _; } constructor(address controller_) GraphDirectory(controller_) {} - - /** - * @notice Set Controller. Deprecated, will revert. - */ - function setController(address) external view override onlyController { - revert ManagedSetControllerDeprecated(); - } - - function controller() public view override returns (IController) { - return IController(CONTROLLER); - } } diff --git a/packages/horizon/test/deployments/Deployments.t.sol b/packages/horizon/test/deployments/Deployments.t.sol index 37fe8b237..3af5e027c 100644 --- a/packages/horizon/test/deployments/Deployments.t.sol +++ b/packages/horizon/test/deployments/Deployments.t.sol @@ -8,10 +8,10 @@ import { GraphBaseTest } from "../GraphBase.t.sol"; contract GraphDeploymentsTest is GraphBaseTest { function testDeployments() public view { - assertEq(address(escrow.GRAPH_PAYMENTS()), address(payments)); - assertEq(address(escrow.GRAPH_TOKEN()), address(token)); - assertEq(address(payments.STAKING()), address(staking)); - assertEq(address(payments.GRAPH_ESCROW()), address(escrow)); - assertEq(address(payments.GRAPH_TOKEN()), address(token)); + // assertEq(address(escrow.GRAPH_PAYMENTS()), address(payments)); + // assertEq(address(escrow.GRAPH_TOKEN()), address(token)); + // assertEq(address(payments.STAKING()), address(staking)); + // assertEq(address(payments.GRAPH_ESCROW()), address(escrow)); + // assertEq(address(payments.GRAPH_TOKEN()), address(token)); } } diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index e74ba0f0b..ac0320651 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -2,21 +2,22 @@ pragma solidity ^0.8.24; pragma abicoder v2; +import { IGraphToken } from "@graphprotocol/horizon/contracts/interfaces/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; -import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; -import { AttestationManager } from "./utilities/AttestationManager.sol"; - import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; -import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; +import { TokenUtils } from "@graphprotocol/horizon/contracts/libraries/TokenUtils.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { Allocation } from "./libraries/Allocation.sol"; import { Attestation } from "./libraries/Attestation.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; +import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; +import { AttestationManager } from "./utilities/AttestationManager.sol"; + /* * @title DisputeManager * @notice Provides a way to align the incentives of participants by having slashing as deterrent @@ -41,6 +42,7 @@ import { Attestation } from "./libraries/Attestation.sol"; * to a EOA or DAO. */ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeManagerV1Storage, IDisputeManager { + using TokenUtils for IGraphToken; using PPMMath for uint256; // -- Events -- @@ -310,7 +312,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM uint256 tokensToReward = _slashIndexer(dispute.indexer, slashAmount); // Give the fisherman their reward and their deposit back - TokenUtils.pushTokens(GRAPH_TOKEN, dispute.fisherman, tokensToReward + dispute.deposit); + _graphToken().pushTokens(dispute.fisherman, tokensToReward + dispute.deposit); if (_isDisputeInConflict(dispute)) { rejectDispute(dispute.relatedDisputeId); @@ -328,7 +330,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM Dispute storage dispute = disputes[disputeId]; // Return deposit to the fisherman - TokenUtils.pushTokens(GRAPH_TOKEN, dispute.fisherman, dispute.deposit); + _graphToken().pushTokens(dispute.fisherman, dispute.deposit); // resolve related dispute if any _drawDisputeInConflict(dispute); @@ -354,7 +356,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM } // Return deposit to the fisherman - TokenUtils.pushTokens(GRAPH_TOKEN, dispute.fisherman, dispute.deposit); + _graphToken().pushTokens(dispute.fisherman, dispute.deposit); // resolve related dispute if any _cancelDisputeInConflict(dispute); @@ -468,7 +470,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM } // Burn the fisherman's deposit - TokenUtils.burnTokens(GRAPH_TOKEN, dispute.deposit); + _graphToken().burnTokens(dispute.deposit); emit DisputeRejected(disputeId, dispute.indexer, dispute.fisherman, dispute.deposit); } @@ -525,7 +527,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM address indexer = getAttestationIndexer(_attestation); // The indexer is disputable - IHorizonStaking.Provision memory provision = GRAPH_STAKING.getProvision(indexer, address(subgraphService)); + IHorizonStaking.Provision memory provision = _graphStaking().getProvision(indexer, address(subgraphService)); if (provision.tokens == 0) { revert DisputeManagerZeroTokens(); } @@ -596,7 +598,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM } // The indexer must be disputable - IHorizonStaking.Provision memory provision = GRAPH_STAKING.getProvision(indexer, address(subgraphService)); + IHorizonStaking.Provision memory provision = _graphStaking().getProvision(indexer, address(subgraphService)); if (provision.tokens == 0) { revert DisputeManagerZeroTokens(); } @@ -658,7 +660,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM } // Transfer tokens to deposit from fisherman to this contract - TokenUtils.pullTokens(GRAPH_TOKEN, msg.sender, _deposit); + _graphToken().pullTokens(msg.sender, _deposit); } /** @@ -669,8 +671,8 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM */ function _slashIndexer(address _indexer, uint256 _slashAmount) private returns (uint256 rewardsAmount) { // Get slashable amount for indexer - IHorizonStaking.Provision memory provision = GRAPH_STAKING.getProvision(_indexer, address(subgraphService)); - IHorizonStaking.DelegationPool memory pool = GRAPH_STAKING.getDelegationPool( + IHorizonStaking.Provision memory provision = _graphStaking().getProvision(_indexer, address(subgraphService)); + IHorizonStaking.DelegationPool memory pool = _graphStaking().getDelegationPool( _indexer, address(subgraphService) ); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 896314bf8..a7a486802 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -160,7 +160,7 @@ contract SubgraphService is function slash(address indexer, bytes calldata data) external override onlyDisputeManager whenNotPaused { (uint256 tokens, uint256 reward) = abi.decode(data, (uint256, uint256)); - GRAPH_STAKING.slash(indexer, tokens, reward, address(DISPUTE_MANAGER)); + _graphStaking().slash(indexer, tokens, reward, address(DISPUTE_MANAGER)); emit ServiceProviderSlashed(indexer, tokens); } @@ -237,9 +237,9 @@ contract SubgraphService is uint256 totalCut = tokensSubgraphService + tokensCurators; // collect fees - uint256 balanceBefore = GRAPH_TOKEN.balanceOf(address(this)); - GRAPH_PAYMENTS.collect(payer, indexer, tokensToCollect, IGraphPayments.PaymentTypes.QueryFee, totalCut); - uint256 balanceAfter = GRAPH_TOKEN.balanceOf(address(this)); + uint256 balanceBefore = _graphToken().balanceOf(address(this)); + _graphPayments().collect(payer, indexer, tokensToCollect, IGraphPayments.PaymentTypes.QueryFee, totalCut); + uint256 balanceAfter = _graphToken().balanceOf(address(this)); if (balanceBefore + totalCut != balanceAfter) { revert SubgraphServiceInconsistentCollection(balanceBefore + totalCut, balanceAfter); } @@ -248,10 +248,10 @@ contract SubgraphService is // distribute curation cut to curators if (tokensCurators > 0) { // we are about to change subgraph signal so we take rewards snapshot - GRAPH_REWARDS_MANAGER.onSubgraphSignalUpdate(subgraphDeploymentId); + _graphRewardsManager().onSubgraphSignalUpdate(subgraphDeploymentId); // Send GRT and bookkeep by calling collect() - GRAPH_TOKEN.transfer(address(CURATION), tokensCurators); + _graphToken().transfer(address(CURATION), tokensCurators); CURATION.collect(subgraphDeploymentId, tokensCurators); } } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index ae280c5a9..175d7def8 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -105,11 +105,11 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager _subgraphDeploymentId, _tokens, // allos can be resized now, so we need to always take snapshot - GRAPH_REWARDS_MANAGER.onSubgraphAllocationUpdate(_subgraphDeploymentId) + _graphRewardsManager().onSubgraphAllocationUpdate(_subgraphDeploymentId) ); // Check that the indexer has enough tokens available - allocationProvisionTracker.lock(GRAPH_STAKING, _indexer, _tokens, _delegationRatio); + allocationProvisionTracker.lock(_graphStaking(), _indexer, _tokens, _delegationRatio); // Update total allocated tokens for the subgraph deployment subgraphAllocatedTokens[allocation.subgraphDeploymentId] = @@ -130,13 +130,13 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Mint indexing rewards, stale POIs get no rewards... uint256 timeSinceLastPOI = block.number - allocation.lastPOIPresentedAt; uint256 tokensRewards = timeSinceLastPOI <= maxPOIStaleness - ? GRAPH_REWARDS_MANAGER.takeRewards(_allocationId) + ? _graphRewardsManager().takeRewards(_allocationId) : 0; // ... but we still take a snapshot to ensure the rewards are not collected with the next valid POI allocations.snapshotRewards( _allocationId, - GRAPH_REWARDS_MANAGER.onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) + _graphRewardsManager().onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) ); allocations.presentPOI(_allocationId); @@ -147,23 +147,23 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Distribute rewards to delegators // TODO: remove the uint8 cast when PRs are merged - uint256 delegatorCut = GRAPH_STAKING.getDelegationFeeCut( + uint256 delegatorCut = _graphStaking().getDelegationFeeCut( allocation.indexer, address(this), uint8(IGraphPayments.PaymentTypes.IndexingFee) ); uint256 tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); - GRAPH_TOKEN.approve(address(GRAPH_STAKING), tokensDelegationRewards); - GRAPH_STAKING.addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); + _graphToken().approve(address(_graphStaking()), tokensDelegationRewards); + _graphStaking().addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); // Distribute rewards to indexer uint256 tokensIndexerRewards = tokensRewards - tokensDelegationRewards; address rewardsDestination = rewardsDestination[allocation.indexer]; if (rewardsDestination == address(0)) { - GRAPH_TOKEN.approve(address(GRAPH_STAKING), tokensIndexerRewards); - GRAPH_STAKING.stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); + _graphToken().approve(address(_graphStaking()), tokensIndexerRewards); + _graphStaking().stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); } else { - GRAPH_TOKEN.transfer(rewardsDestination, tokensIndexerRewards); + _graphToken().transfer(rewardsDestination, tokensIndexerRewards); } emit AllocationCollected( @@ -194,13 +194,13 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Update provision tracker uint256 oldTokens = allocation.tokens; if (_tokens > oldTokens) { - allocationProvisionTracker.lock(GRAPH_STAKING, allocation.indexer, _tokens - oldTokens, _delegationRatio); + allocationProvisionTracker.lock(_graphStaking(), allocation.indexer, _tokens - oldTokens, _delegationRatio); } else { allocationProvisionTracker.release(allocation.indexer, oldTokens - _tokens); } // Calculate rewards that have been accrued since the last snapshot but not yet issued - uint256 accRewardsPerAllocatedToken = GRAPH_REWARDS_MANAGER.onSubgraphAllocationUpdate( + uint256 accRewardsPerAllocatedToken = _graphRewardsManager().onSubgraphAllocationUpdate( allocation.subgraphDeploymentId ); uint256 accRewardsPending = accRewardsPerAllocatedToken - allocation.accRewardsPerAllocatedToken; diff --git a/yarn.lock b/yarn.lock index 1258d7100..6d884fac8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2858,6 +2858,7 @@ __metadata: prettier-plugin-solidity: "npm:^1.3.1" solhint: "npm:^4.1.1" solhint-graph-config: "workspace:^0.0.1" + solhint-plugin-graph: "workspace:^0.0.1" solidity-coverage: "npm:^0.7.16" ts-node: "npm:^10.9.1" typechain: "npm:^5.0.0" From 870d71eb58e5002fe80516b899c6fb0a5d2e8b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 15:06:03 -0300 Subject: [PATCH 031/277] chore(payments): rename payments escrow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/GraphDirectory.sol | 14 +++++++------- .../{IGraphEscrow.sol => IPaymentsEscrow.sol} | 2 +- .../PaymentsEscrow.sol} | 6 +++--- .../PaymentsEscrowStorage.sol} | 8 ++++---- .../staking/StakingBackwardsCompatibility.sol | 1 - packages/horizon/test/GraphBase.t.sol | 6 +++--- 6 files changed, 18 insertions(+), 19 deletions(-) rename packages/horizon/contracts/interfaces/{IGraphEscrow.sol => IPaymentsEscrow.sol} (98%) rename packages/horizon/contracts/{escrow/GraphEscrow.sol => payments/PaymentsEscrow.sol} (97%) rename packages/horizon/contracts/{escrow/GraphEscrowStorage.sol => payments/PaymentsEscrowStorage.sol} (72%) diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index d76bda88f..24cfa14e0 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -6,7 +6,7 @@ import { IController } from "@graphprotocol/contracts/contracts/governance/ICont import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; -import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; +import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; @@ -26,7 +26,7 @@ abstract contract GraphDirectory { IGraphToken private immutable GRAPH_TOKEN; IHorizonStaking private immutable GRAPH_STAKING; IGraphPayments private immutable GRAPH_PAYMENTS; - IGraphEscrow private immutable GRAPH_ESCROW; + IPaymentsEscrow private immutable GRAPH_ESCROW; // Legacy Graph contracts // Required for StakingBackwardCompatibility @@ -41,7 +41,7 @@ abstract contract GraphDirectory { IGraphToken graphToken, IHorizonStaking graphStaking, IGraphPayments graphPayments, - IGraphEscrow graphEscrow, + IPaymentsEscrow graphEscrow, IEpochManager graphEpochManager, IRewardsManager graphRewardsManager, ICuration graphCuration, @@ -59,7 +59,7 @@ abstract contract GraphDirectory { GRAPH_TOKEN = IGraphToken(_getContractFromController("GraphToken")); GRAPH_STAKING = IHorizonStaking(_getContractFromController("Staking")); GRAPH_PAYMENTS = IGraphPayments(_getContractFromController("GraphPayments")); - GRAPH_ESCROW = IGraphEscrow(_getContractFromController("GraphEscrow")); + GRAPH_ESCROW = IPaymentsEscrow(_getContractFromController("PaymentsEscrow")); GRAPH_EPOCH_MANAGER = IEpochManager(_getContractFromController("EpochManager")); GRAPH_REWARDS_MANAGER = IRewardsManager(_getContractFromController("RewardsManager")); GRAPH_CURATION = ICuration(_getContractFromController("Curation")); @@ -94,7 +94,7 @@ abstract contract GraphDirectory { return GRAPH_PAYMENTS; } - function _graphEscrow() internal view returns (IGraphEscrow) { + function _graphEscrow() internal view returns (IPaymentsEscrow) { return GRAPH_ESCROW; } @@ -114,8 +114,8 @@ abstract contract GraphDirectory { return GRAPH_TOKEN_GATEWAY; } - function _getContractFromController(bytes memory __contractName) private view returns (address) { - address contractAddress = GRAPH_CONTROLLER.getContractProxy(keccak256(contractName)); + function _getContractFromController(bytes memory _contractName) private view returns (address) { + address contractAddress = GRAPH_CONTROLLER.getContractProxy(keccak256(_contractName)); if (contractAddress == address(0)) { revert GraphDirectoryInvalidZeroAddress(); } diff --git a/packages/horizon/contracts/interfaces/IGraphEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol similarity index 98% rename from packages/horizon/contracts/interfaces/IGraphEscrow.sol rename to packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 9b638a87e..73acc6592 100644 --- a/packages/horizon/contracts/interfaces/IGraphEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.24; import { IGraphPayments } from "./IGraphPayments.sol"; -interface IGraphEscrow { +interface IPaymentsEscrow { struct EscrowAccount { uint256 balance; // Total escrow balance for a sender-receiver pair uint256 amountThawing; // Amount of escrow currently being thawed diff --git a/packages/horizon/contracts/escrow/GraphEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol similarity index 97% rename from packages/horizon/contracts/escrow/GraphEscrow.sol rename to packages/horizon/contracts/payments/PaymentsEscrow.sol index e6d021425..7b324606c 100644 --- a/packages/horizon/contracts/escrow/GraphEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -2,15 +2,15 @@ pragma solidity ^0.8.24; import { IGraphToken } from "../interfaces/IGraphToken.sol"; -import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; -import { GraphEscrowStorageV1Storage } from "./GraphEscrowStorage.sol"; +import { PaymentsEscrowV1Storage } from "./PaymentsEscrowStorage.sol"; -contract GraphEscrow is IGraphEscrow, GraphEscrowStorageV1Storage, GraphDirectory { +contract PaymentsEscrow is IPaymentsEscrow, PaymentsEscrowV1Storage, GraphDirectory { using TokenUtils for IGraphToken; // -- Events -- diff --git a/packages/horizon/contracts/escrow/GraphEscrowStorage.sol b/packages/horizon/contracts/payments/PaymentsEscrowStorage.sol similarity index 72% rename from packages/horizon/contracts/escrow/GraphEscrowStorage.sol rename to packages/horizon/contracts/payments/PaymentsEscrowStorage.sol index 89a49e756..2607ab801 100644 --- a/packages/horizon/contracts/escrow/GraphEscrowStorage.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrowStorage.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphEscrow } from "../interfaces/IGraphEscrow.sol"; +import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; -contract GraphEscrowStorageV1Storage { +contract PaymentsEscrowV1Storage { // Authorized collectors - mapping(address sender => mapping(address dataService => IGraphEscrow.Collector collector)) + mapping(address sender => mapping(address dataService => IPaymentsEscrow.Collector collector)) public authorizedCollectors; // Stores how much escrow each sender has deposited for each receiver, as well as thawing information - mapping(address sender => mapping(address receiver => IGraphEscrow.EscrowAccount escrowAccount)) + mapping(address sender => mapping(address receiver => IPaymentsEscrow.EscrowAccount escrowAccount)) public escrowAccounts; // The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 30a667b77..a570242f4 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -97,7 +97,6 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor { // -- Pull tokens from the sender -- - IGraphToken graphToken = _graphToken(); _graphToken().pullTokens(msg.sender, queryFees); // -- Collect protocol tax -- diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 28fa8f2c8..36721ed2c 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; -import { GraphEscrow } from "contracts/escrow/GraphEscrow.sol"; +import { PaymentsEscrow } from "contracts/payments/PaymentsEscrow.sol"; import { GraphPayments } from "contracts/payments/GraphPayments.sol"; import { IHorizonStaking } from "contracts/interfaces/IHorizonStaking.sol"; import { HorizonStaking } from "contracts/staking/HorizonStaking.sol"; @@ -21,7 +21,7 @@ abstract contract GraphBaseTest is Test, Constants { Controller public controller; MockGRTToken public token; GraphPayments public payments; - GraphEscrow public escrow; + PaymentsEscrow public escrow; IHorizonStaking public staking; HorizonStaking private stakingBase; @@ -139,7 +139,7 @@ abstract contract GraphBaseTest is Test, Constants { address(controller), protocolPaymentCut ); - escrow = new GraphEscrow{salt: saltEscrow}( + escrow = new PaymentsEscrow{salt: saltEscrow}( address(controller), revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod From f628fea033deb64e8f29345b7b8290e93ff1f8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 15:15:23 -0300 Subject: [PATCH 032/277] chore(contracts): dont apply underscore rules on legacy code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/contracts/.solhint.json | 14 ---------- packages/contracts/.solhintignore | 8 ------ .../contracts/arbitrum/ITokenGateway.sol | 13 +++++---- packages/contracts/package.json | 2 +- packages/contracts/solhint.config.js | 28 +++++++++++++++++++ packages/contracts/tsconfig.json | 1 + 6 files changed, 37 insertions(+), 29 deletions(-) delete mode 100644 packages/contracts/.solhint.json delete mode 100644 packages/contracts/.solhintignore create mode 100644 packages/contracts/solhint.config.js diff --git a/packages/contracts/.solhint.json b/packages/contracts/.solhint.json deleted file mode 100644 index e52cf9346..000000000 --- a/packages/contracts/.solhint.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "solhint:recommended", - "plugins": ["prettier"], - "rules": { - "prettier/prettier": "error", - "func-visibility": ["warn", { "ignoreConstructors": true }], - "compiler-version": ["off"], - "constructor-syntax": "warn", - "quotes": ["error", "double"], - "reason-string": ["off"], - "not-rely-on-time": "off", - "no-empty-blocks": "off" - } -} diff --git a/packages/contracts/.solhintignore b/packages/contracts/.solhintignore deleted file mode 100644 index b36dffeb7..000000000 --- a/packages/contracts/.solhintignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules - -./contracts/bancor -./contracts/discovery/erc1056 -./contracts/rewards/RewardsManager.sol -./contracts/staking/libs/LibFixedMath.sol -./contracts/tests/ens -./contracts/tests/testnet/GSRManager.sol diff --git a/packages/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/contracts/contracts/arbitrum/ITokenGateway.sol index 41b11f7fc..6ac47d715 100644 --- a/packages/contracts/contracts/arbitrum/ITokenGateway.sol +++ b/packages/contracts/contracts/arbitrum/ITokenGateway.sol @@ -53,14 +53,15 @@ interface ITokenGateway { uint256 maxas, uint256 gasPiceBid, bytes calldata data - ) external payable returns (bytes memory); + ) external payable returns (bytes memory); function finalizeInboundTransfer( - address token, address from, - address to, - uint256 amount, - bytes calldata data - )external payable; + address token, + address from, + address to, + uint256 amount, + bytes calldata data + ) external payable; /** * @notice Calculate the address used when bridging an ERC20 token diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 0f112bcc1..85f02990d 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -97,7 +97,7 @@ "test:upgrade": "scripts/upgrade", "lint": "yarn lint:ts && yarn lint:sol", "lint:ts": "eslint '**/*.{js,ts}' --fix", - "lint:sol": "prettier --write 'contracts/**/*.sol' && solhint --fix --noPrompt contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", + "lint:sol": "prettier --write 'contracts/**/*.sol' && solhint --fix --noPrompt contracts/**/*.sol --config solhint.config.js", "analyze": "scripts/analyze", "myth": "scripts/myth", "flatten": "scripts/flatten && scripts/clean", diff --git a/packages/contracts/solhint.config.js b/packages/contracts/solhint.config.js new file mode 100644 index 000000000..b8e918530 --- /dev/null +++ b/packages/contracts/solhint.config.js @@ -0,0 +1,28 @@ +module.exports = { + plugins: ['graph'], + extends: 'solhint:recommended', + rules: { + // best practices + 'no-empty-blocks': 'off', + 'constructor-syntax': 'warn', + + // style rules + 'private-vars-leading-underscore': 'off', // see graph/leading-underscore + 'const-name-snakecase': 'warn', + 'named-parameters-mapping': 'warn', + 'imports-on-top': 'warn', + 'ordering': 'warn', + 'visibility-modifier-order': 'warn', + + // miscellaneous + 'quotes': ['error', 'double'], + + // security + 'compiler-version': ['off'], + 'func-visibility': ['warn', { ignoreConstructors: true }], + 'not-rely-on-time': 'off', + + // graph + // 'graph/leading-underscore': 'warn', // Contracts were originally written with a different style + }, +} diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index a12f7de23..a876614c5 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -13,6 +13,7 @@ "truffle.js", "eslint.config.js", "prettier.config.js", + "solhint.config.js", "hardhat.config.ts", "index.d.ts", "scripts/**/*.ts", From 18f9a97a900dd9fdce0a47755d0378088cc6df79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 15:22:56 -0300 Subject: [PATCH 033/277] feat: add multicall to payments contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/IPaymentsEscrow.sol | 3 -- .../contracts/payments/GraphPayments.sol | 3 +- .../contracts/payments/PaymentsEscrow.sol | 22 +---------- .../contracts/staking/HorizonStaking.sol | 2 +- packages/horizon/test/escrow/deposit.t.sol | 39 ------------------- 5 files changed, 5 insertions(+), 64 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 73acc6592..368b2d6d0 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -20,9 +20,6 @@ interface IPaymentsEscrow { // Deposit funds into the escrow for a receiver function deposit(address receiver, uint256 amount) external; - // Deposit funds into the escrow for multiple receivers - function depositMany(address[] calldata receivers, uint256[] calldata amounts) external; - // Requests to thaw a specific amount of escrow from a receiver's escrow account function thaw(address receiver, uint256 amount) external; diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index f5e0d2031..85fc17314 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -5,12 +5,13 @@ import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; -contract GraphPayments is IGraphPayments, GraphPaymentsStorageV1Storage, GraphDirectory { +contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Storage, IGraphPayments { using TokenUtils for IGraphToken; uint256 private immutable MAX_PPM = 1000000; // 100% in parts per million diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 7b324606c..54f4ed0af 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -5,12 +5,13 @@ import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; import { PaymentsEscrowV1Storage } from "./PaymentsEscrowStorage.sol"; -contract PaymentsEscrow is IPaymentsEscrow, PaymentsEscrowV1Storage, GraphDirectory { +contract PaymentsEscrow is Multicall, GraphDirectory, PaymentsEscrowV1Storage, IPaymentsEscrow { using TokenUtils for IGraphToken; // -- Events -- @@ -110,25 +111,6 @@ contract PaymentsEscrow is IPaymentsEscrow, PaymentsEscrowV1Storage, GraphDirect emit Deposit(msg.sender, receiver, amount); } - // Deposit funds into the escrow for multiple receivers - function depositMany(address[] calldata receivers, uint256[] calldata amounts) external { - if (receivers.length != amounts.length) { - revert GraphEscrowInputsLengthMismatch(); - } - - uint256 totalAmount = 0; - for (uint256 i = 0; i < receivers.length; i++) { - address receiver = receivers[i]; - uint256 amount = amounts[i]; - - totalAmount += amount; - escrowAccounts[msg.sender][receiver].balance += amount; - emit Deposit(msg.sender, receiver, amount); - } - - _graphToken().pullTokens(msg.sender, totalAmount); - } - // Requests to thaw a specific amount of escrow from a receiver's escrow account function thaw(address receiver, uint256 amount) external { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 77812d5b3..95c297ffd 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -8,8 +8,8 @@ import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; - import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; + import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol index d7898bd37..48574880e 100644 --- a/packages/horizon/test/escrow/deposit.t.sol +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -11,43 +11,4 @@ contract GraphEscrowDepositTest is GraphEscrowTest { (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); assertEq(indexerEscrowBalance, amount); } - - function testDeposit_ManyDeposits(uint256 amount) public useGateway approveEscrow(amount) { - uint256 amountOne = amount / 2; - uint256 amountTwo = amount - amountOne; - - address otherIndexer = address(0xB3); - address[] memory indexers = new address[](2); - indexers[0] = users.indexer; - indexers[1] = otherIndexer; - - uint256[] memory amounts = new uint256[](2); - amounts[0] = amountOne; - amounts[1] = amountTwo; - - escrow.depositMany(indexers, amounts); - - (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); - assertEq(indexerEscrowBalance, amountOne); - - (uint256 otherIndexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, otherIndexer); - assertEq(otherIndexerEscrowBalance, amountTwo); - } - - function testDeposit_RevertWhen_ManyDepositsInputsLengthMismatch( - uint256 amount - ) public useGateway approveEscrow(amount) { - address otherIndexer = address(0xB3); - address[] memory indexers = new address[](2); - indexers[0] = users.indexer; - indexers[1] = otherIndexer; - - uint256[] memory amounts = new uint256[](1); - amounts[0] = 1000 ether; - - // revert - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInputsLengthMismatch()"); - vm.expectRevert(expectedError); - escrow.depositMany(indexers, amounts); - } } \ No newline at end of file From ffbe9138e60e469c3a632dc177bf3328501181af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 15:24:15 -0300 Subject: [PATCH 034/277] chore: remove payments escrow storage contract, not upgradeable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/payments/PaymentsEscrow.sol | 21 ++++++++++++++-- .../payments/PaymentsEscrowStorage.sol | 24 ------------------- 2 files changed, 19 insertions(+), 26 deletions(-) delete mode 100644 packages/horizon/contracts/payments/PaymentsEscrowStorage.sol diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 54f4ed0af..d00312e05 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -9,11 +9,28 @@ import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; -import { PaymentsEscrowV1Storage } from "./PaymentsEscrowStorage.sol"; -contract PaymentsEscrow is Multicall, GraphDirectory, PaymentsEscrowV1Storage, IPaymentsEscrow { +contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { using TokenUtils for IGraphToken; + // Authorized collectors + mapping(address sender => mapping(address dataService => IPaymentsEscrow.Collector collector)) + public authorizedCollectors; + + // Stores how much escrow each sender has deposited for each receiver, as well as thawing information + mapping(address sender => mapping(address receiver => IPaymentsEscrow.EscrowAccount escrowAccount)) + public escrowAccounts; + + // The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation + // This is a precautionary measure to avoid inadvertedly locking funds for too long + uint256 public constant MAX_THAWING_PERIOD = 90 days; + + // Thawing period for authorized collectors + uint256 public immutable REVOKE_COLLECTOR_THAWING_PERIOD; + + // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn + uint256 public immutable WITHDRAW_ESCROW_THAWING_PERIOD; + // -- Events -- event AuthorizedCollector(address indexed sender, address indexed dataService); diff --git a/packages/horizon/contracts/payments/PaymentsEscrowStorage.sol b/packages/horizon/contracts/payments/PaymentsEscrowStorage.sol deleted file mode 100644 index 2607ab801..000000000 --- a/packages/horizon/contracts/payments/PaymentsEscrowStorage.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; - -import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; - -contract PaymentsEscrowV1Storage { - // Authorized collectors - mapping(address sender => mapping(address dataService => IPaymentsEscrow.Collector collector)) - public authorizedCollectors; - - // Stores how much escrow each sender has deposited for each receiver, as well as thawing information - mapping(address sender => mapping(address receiver => IPaymentsEscrow.EscrowAccount escrowAccount)) - public escrowAccounts; - - // The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation - // This is a precautionary measure to avoid inadvertedly locking funds for too long - uint256 public constant MAX_THAWING_PERIOD = 90 days; - - // Thawing period for authorized collectors - uint256 public immutable REVOKE_COLLECTOR_THAWING_PERIOD; - - // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn - uint256 public immutable WITHDRAW_ESCROW_THAWING_PERIOD; -} From e8c53790b5aa677f1e3e7f5ab1cb298f9237b3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 15:39:25 -0300 Subject: [PATCH 035/277] feat(ss): add rewards destination functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../subgraph-service/contracts/SubgraphService.sol | 9 ++++++++- .../contracts/utilities/AllocationManager.sol | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index a7a486802..ffce937f8 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -74,7 +74,10 @@ contract SubgraphService is address indexer, bytes calldata data ) external override onlyProvisionAuthorized(indexer) whenNotPaused { - (string memory url, string memory geohash) = abi.decode(data, (string, string)); + (string memory url, string memory geohash, address rewardsDestination) = abi.decode( + data, + (string, string, address) + ); // Must provide a URL if (bytes(url).length == 0) { @@ -89,6 +92,10 @@ contract SubgraphService is // Register the indexer indexers[indexer] = Indexer({ registeredAt: block.timestamp, url: url, geoHash: geohash }); + if (rewardsDestination != address(0)) { + _setRewardsDestination(indexer, rewardsDestination); + } + // Ensure the service provider created a valid provision for the data service // and accept it in the staking contract _acceptProvision(indexer); diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 175d7def8..182827b12 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -70,6 +70,8 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager bytes32 indexed subgraphDeploymentId ); + event RewardsDestinationSet(address indexed indexer, address rewardsDestination); + error AllocationManagerInvalidAllocationProof(address signer, address allocationId); error AllocationManagerInvalidAllocationId(); error AllocationManagerZeroTokensAllocation(address allocationId); @@ -79,6 +81,10 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager constructor(string memory name, string memory version) EIP712(name, version) {} + function setRewardsDestination(address rewardsDestination) external { + _setRewardsDestination(msg.sender, rewardsDestination); + } + function _migrateLegacyAllocation(address _indexer, address _allocationId, bytes32 _subgraphDeploymentId) internal { legacyAllocations.migrate(_indexer, _allocationId, _subgraphDeploymentId); emit LegacyAllocationMigrated(_indexer, _allocationId, _subgraphDeploymentId); @@ -233,6 +239,11 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager return allocations[_allocationId]; } + function _setRewardsDestination(address _indexer, address _rewardsDestination) internal { + rewardsDestination[_indexer] = _rewardsDestination; + emit RewardsDestinationSet(_indexer, _rewardsDestination); + } + function _getAllocation(address _allocationId) internal view returns (Allocation.State memory) { return allocations.get(_allocationId); } From 3a67294a6cf899ab4111c102d5504bd3d0d1a8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 21 May 2024 16:33:24 -0300 Subject: [PATCH 036/277] feat: unify data service collection functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/IDataService.sol | 42 ++++++------------- .../contracts/interfaces/IGraphPayments.sol | 3 +- .../contracts/payments/GraphPayments.sol | 23 +++++++++- .../contracts/payments/PaymentsEscrow.sol | 4 +- .../contracts/SubgraphService.sol | 41 ++++++++---------- .../contracts/utilities/AllocationManager.sol | 37 ++++++++++------ 6 files changed, 79 insertions(+), 71 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IDataService.sol b/packages/horizon/contracts/interfaces/IDataService.sol index 4064d4444..e6ca8fabe 100644 --- a/packages/horizon/contracts/interfaces/IDataService.sol +++ b/packages/horizon/contracts/interfaces/IDataService.sol @@ -44,19 +44,12 @@ interface IDataService { event ServiceStopped(address indexed serviceProvider); /** - * @notice Emitted when a service provider collects payment for the service being provided. + * @notice Emitted when a service provider collects payment. * @param serviceProvider The address of the service provider. + * @param feeType The type of fee to collect as defined in {GraphPayments}. * @param tokens The amount of tokens collected. */ - event ServicePaymentCollected(address indexed serviceProvider, uint256 tokens); - - /** - * @notice Emitted when a service provider redeems fees. - * @param serviceProvider The address of the service provider. - * @param feeType The type of fee to redeem as defined in {GraphPayments}. - * @param tokens The amount of tokens redeemed. - */ - event ServiceFeesRedeemed( + event ServicePaymentCollected( address indexed serviceProvider, IGraphPayments.PaymentTypes indexed feeType, uint256 tokens @@ -114,21 +107,6 @@ interface IDataService { */ function startService(address serviceProvider, bytes calldata data) external; - /** - * @notice Service provider collects payment for the service being provided. - * @dev This is payment owed to a service provided for ongoing work required to fullfil - * customer requests. How the funds for the payment are procured is up to the data service. - * - * Emits a {ServicePaymentCollected} event. - * - * NOTE: Data services that are vetted by the Graph Council might qualify for a portion of - * the protocol issuance to cover these payments. In this case, the funds are taken by - * interacting with the rewards manager contract. - * @param serviceProvider The address of the service provider. - * @param data Custom data, usage defined by the data service. - */ - function collectServicePayment(address serviceProvider, bytes calldata data) external; - /** * @notice Service provider stops providing the service. * @dev Emits a {ServiceStopped} event. @@ -138,17 +116,21 @@ interface IDataService { function stopService(address serviceProvider, bytes calldata data) external; /** - * @notice Redeeems fees earnt by the service provider. + * @notice Collects payment earnt by the service provider. * @dev The implementation of this function is expected to interact with {GraphPayments} - * to collect fees from the service payer, which is done via {IGraphPayments-collect}. + * to collect payment from the service payer, which is done via {IGraphPayments-collect}. * @param serviceProvider The address of the service provider. * - * Emits a {ServicePaymentRedeemed} event. + * Emits a {ServicePaymentCollected} event. * - * @param feeType The type of fee to redeem as defined in {GraphPayments}. + * NOTE: Data services that are vetted by the Graph Council might qualify for a portion of + * protocol issuance to cover for these payments. In this case, the funds are taken by + * interacting with the rewards manager contract instead of the {GraphPayments} contract. + * @param serviceProvider The address of the service provider. + * @param feeType The type of fee to collect as defined in {GraphPayments}. * @param data Custom data, usage defined by the data service. */ - function redeem(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external; + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external; /** * @notice Slash a service provider for misbehaviour. diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 0beda3543..a42035ef9 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -5,7 +5,8 @@ interface IGraphPayments { // Payment types enum PaymentTypes { QueryFee, - IndexingFee + IndexingFee, + IndexingRewards } // collect funds from a sender, pay cuts and forward the rest to the receiver diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 85fc17314..2ea903807 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -15,6 +15,16 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora using TokenUtils for IGraphToken; uint256 private immutable MAX_PPM = 1000000; // 100% in parts per million + + event GraphPaymentsCollected( + address indexed sender, + address indexed receiver, + uint256 tokensReceiver, + uint256 tokensDelegationPool, + uint256 tokensDataService, + uint256 tokensProtocol + ); + // -- Errors -- error GraphPaymentsNotThawing(); @@ -54,10 +64,21 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora // Get delegation cut uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, uint8(paymentType)); uint256 tokensDelegationPool = (amount * delegationFeeCut) / MAX_PPM; - _graphStaking().addToDelegationPool(receiver, dataService, tokensDelegationPool); + if (tokensDelegationPool > 0) { + _graphStaking().addToDelegationPool(receiver, dataService, tokensDelegationPool); + } // Pay the rest to the receiver uint256 tokensReceiver = amount - tokensProtocol - tokensDataService - tokensDelegationPool; _graphToken().pushTokens(receiver, tokensReceiver); + + emit GraphPaymentsCollected( + msg.sender, + receiver, + tokensReceiver, + tokensDelegationPool, + tokensDataService, + tokensProtocol + ); } } diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index d00312e05..d0e560b5e 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -47,7 +47,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { uint256 thawEndTimestamp ); event Withdraw(address indexed sender, address indexed receiver, uint256 amount); - event Collect(address indexed sender, address indexed receiver, uint256 amount); + event EscrowCollected(address indexed sender, address indexed receiver, uint256 amount); // -- Errors -- @@ -212,7 +212,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } account.balance -= amount; - emit Collect(sender, receiver, amount); + emit EscrowCollected(sender, receiver, amount); // Approve tokens so GraphPayments can pull them _graphToken().approve(address(_graphPayments()), amount); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index ffce937f8..e7484247b 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -33,7 +33,7 @@ contract SubgraphService is using PPMMath for uint256; using Allocation for mapping(address => Allocation.State); - event QueryFeesRedeemed( + event QueryFeesCollected( address serviceProvider, address payer, uint256 tokensCollected, @@ -122,15 +122,6 @@ contract SubgraphService is emit ServiceStarted(indexer); } - function collectServicePayment( - address indexer, - bytes calldata data - ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { - (address allocationId, bytes32 poi) = abi.decode(data, (address, bytes32)); - uint256 rewards = _collectPOIRewards(allocationId, poi); - emit ServicePaymentCollected(indexer, rewards); - } - function stopService( address indexer, bytes calldata data @@ -148,21 +139,22 @@ contract SubgraphService is _resizeAllocation(allocationId, tokens, delegationRatio); } - // TODO: Does this design allow custom payment types?! - function redeem( + function collect( address indexer, - IGraphPayments.PaymentTypes feeType, + IGraphPayments.PaymentTypes paymentType, bytes calldata data ) external override onlyRegisteredIndexer(indexer) whenNotPaused { - uint256 feesCollected = 0; + uint256 paymentCollected = 0; - if (feeType == IGraphPayments.PaymentTypes.QueryFee) { - feesCollected = _redeemQueryFees(abi.decode(data, (ITAPVerifier.SignedRAV))); + if (paymentType == IGraphPayments.PaymentTypes.QueryFee) { + paymentCollected = _collectQueryFees(data); + } else if (paymentType == IGraphPayments.PaymentTypes.IndexingRewards) { + paymentCollected = _collectIndexingRewards(data); } else { - revert SubgraphServiceInvalidPaymentType(feeType); + revert SubgraphServiceInvalidPaymentType(paymentType); } - emit ServiceFeesRedeemed(indexer, feeType, feesCollected); + emit ServicePaymentCollected(indexer, paymentType, paymentCollected); } function slash(address indexer, bytes calldata data) external override onlyDisputeManager whenNotPaused { @@ -206,16 +198,17 @@ contract SubgraphService is return (verifierCut, type(uint32).max); } - function _redeemQueryFees(ITAPVerifier.SignedRAV memory _signedRAV) private returns (uint256 feesCollected) { - address indexer = _signedRAV.rav.serviceProvider; - address allocationId = abi.decode(_signedRAV.rav.metadata, (address)); + function _collectQueryFees(bytes memory _data) private returns (uint256 feesCollected) { + ITAPVerifier.SignedRAV memory signedRav = abi.decode(_data, (ITAPVerifier.SignedRAV)); + address indexer = signedRav.rav.serviceProvider; + address allocationId = abi.decode(signedRav.rav.metadata, (address)); // release expired stake claims _releaseStake(IGraphPayments.PaymentTypes.QueryFee, indexer, 0); // validate RAV and calculate tokens to collect - address payer = TAP_VERIFIER.verify(_signedRAV); - uint256 tokens = _signedRAV.rav.valueAggregate; + address payer = TAP_VERIFIER.verify(signedRav); + uint256 tokens = signedRav.rav.valueAggregate; uint256 tokensAlreadyCollected = tokensCollected[indexer][payer]; if (tokens <= tokensAlreadyCollected) { revert SubgraphServiceInconsistentRAVTokens(tokens, tokensAlreadyCollected); @@ -263,7 +256,7 @@ contract SubgraphService is } } - emit QueryFeesRedeemed(indexer, payer, tokensToCollect, tokensCurators, tokensSubgraphService); + emit QueryFeesCollected(indexer, payer, tokensToCollect, tokensCurators, tokensSubgraphService); return tokensToCollect; } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 182827b12..f20a5ab90 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -35,7 +35,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager uint256 tokens ); - event AllocationCollected( + event IndexingRewardsCollected( address indexed indexer, address indexed allocationId, bytes32 indexed subgraphDeploymentId, @@ -128,26 +128,35 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Update POI timestamp and take rewards snapshot even for 0 rewards // This ensures the rewards are actually skipped and not collected with the next valid POI - function _collectPOIRewards(address _allocationId, bytes32 _poi) internal returns (uint256) { - if (_poi == bytes32(0)) revert AllocationManagerInvalidZeroPOI(); + function _collectIndexingRewards(bytes memory _data) internal returns (uint256) { + (address allocationId, bytes32 poi) = abi.decode(_data, (address, bytes32)); + if (poi == bytes32(0)) revert AllocationManagerInvalidZeroPOI(); - Allocation.State memory allocation = allocations.get(_allocationId); + Allocation.State memory allocation = allocations.get(allocationId); // Mint indexing rewards, stale POIs get no rewards... uint256 timeSinceLastPOI = block.number - allocation.lastPOIPresentedAt; uint256 tokensRewards = timeSinceLastPOI <= maxPOIStaleness - ? _graphRewardsManager().takeRewards(_allocationId) + ? _graphRewardsManager().takeRewards(allocationId) : 0; // ... but we still take a snapshot to ensure the rewards are not collected with the next valid POI allocations.snapshotRewards( - _allocationId, + allocationId, _graphRewardsManager().onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) ); - allocations.presentPOI(_allocationId); + allocations.presentPOI(allocationId); if (tokensRewards == 0) { - emit AllocationCollected(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, 0, 0, 0, _poi); + emit IndexingRewardsCollected( + allocation.indexer, + allocationId, + allocation.subgraphDeploymentId, + 0, + 0, + 0, + poi + ); return tokensRewards; } @@ -159,8 +168,10 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager uint8(IGraphPayments.PaymentTypes.IndexingFee) ); uint256 tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); - _graphToken().approve(address(_graphStaking()), tokensDelegationRewards); - _graphStaking().addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); + if (tokensDelegationRewards > 0) { + _graphToken().approve(address(_graphStaking()), tokensDelegationRewards); + _graphStaking().addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); + } // Distribute rewards to indexer uint256 tokensIndexerRewards = tokensRewards - tokensDelegationRewards; @@ -172,14 +183,14 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager _graphToken().transfer(rewardsDestination, tokensIndexerRewards); } - emit AllocationCollected( + emit IndexingRewardsCollected( allocation.indexer, - _allocationId, + allocationId, allocation.subgraphDeploymentId, tokensRewards, tokensIndexerRewards, tokensDelegationRewards, - _poi + poi ); return tokensRewards; From a3c79a57c5b86c8a4bfc77697c2a2168e3ccdb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 22 May 2024 12:03:53 -0300 Subject: [PATCH 037/277] feat: add TAP collector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/IGraphPayments.sol | 4 +- .../interfaces/IPaymentsCollector.sol | 9 + .../contracts/interfaces/IPaymentsEscrow.sol | 6 +- .../{ITAPVerifier.sol => ITAPCollector.sol} | 11 +- .../contracts/payments/GraphPayments.sol | 20 +- .../contracts/payments/PaymentsEscrow.sol | 66 +++--- .../payments/collectors/TAPCollector.sol | 123 ++++++++++ .../payments/collectors/TAPVerifier.sol | 220 ------------------ packages/horizon/test/escrow/collect.t.sol | 8 +- .../horizon/test/payments/GraphPayments.t.sol | 2 +- .../contracts/SubgraphService.sol | 77 +++--- .../contracts/SubgraphServiceStorage.sol | 4 +- .../contracts/interfaces/ISubgraphService.sol | 6 +- .../contracts/utilities/Directory.sol | 6 +- 14 files changed, 233 insertions(+), 329 deletions(-) create mode 100644 packages/horizon/contracts/interfaces/IPaymentsCollector.sol rename packages/horizon/contracts/interfaces/{ITAPVerifier.sol => ITAPCollector.sol} (56%) create mode 100644 packages/horizon/contracts/payments/collectors/TAPCollector.sol delete mode 100644 packages/horizon/contracts/payments/collectors/TAPVerifier.sol diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index a42035ef9..acad67e99 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -11,10 +11,10 @@ interface IGraphPayments { // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( + PaymentTypes paymentType, address receiver, - address dataService, uint256 tokens, - PaymentTypes paymentType, + address dataService, uint256 tokensDataService ) external; } diff --git a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol new file mode 100644 index 000000000..76525bd03 --- /dev/null +++ b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IGraphPayments } from "./IGraphPayments.sol"; + +interface IPaymentsCollector { + function collect(IGraphPayments.PaymentTypes paymentType, bytes memory data) external returns (uint256); +} diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 368b2d6d0..cd7665e73 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -28,11 +28,11 @@ interface IPaymentsEscrow { // Collect from escrow for a receiver using sender's deposit function collect( - address sender, + IGraphPayments.PaymentTypes paymentType, + address payer, address receiver, + uint256 tokens, address dataService, - uint256 amount, - IGraphPayments.PaymentTypes paymentType, uint256 tokensDataService ) external; diff --git a/packages/horizon/contracts/interfaces/ITAPVerifier.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol similarity index 56% rename from packages/horizon/contracts/interfaces/ITAPVerifier.sol rename to packages/horizon/contracts/interfaces/ITAPCollector.sol index 2cbfdf052..217f7a1a6 100644 --- a/packages/horizon/contracts/interfaces/ITAPVerifier.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -interface ITAPVerifier { +import { IPaymentsCollector } from "./IPaymentsCollector.sol"; + +interface ITAPCollector is IPaymentsCollector { struct ReceiptAggregateVoucher { address dataService; address serviceProvider; @@ -14,11 +16,4 @@ interface ITAPVerifier { ReceiptAggregateVoucher rav; bytes signature; // 65 bytes: r (32 Bytes) || s (32 Bytes) || v (1 Byte) } - - struct SenderAuthorization { - address sender; // Sender the signer is authorized to sign for - uint256 thawEndTimestamp; // Timestamp at which thawing period ends (zero if not thawing) - } - - function verify(SignedRAV calldata rav) external returns (address sender); } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 2ea903807..7644d68cf 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -19,6 +19,7 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora event GraphPaymentsCollected( address indexed sender, address indexed receiver, + address indexed dataService, uint256 tokensReceiver, uint256 tokensDelegationPool, uint256 tokensDataService, @@ -46,16 +47,16 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( - address receiver, // serviceProvider - address dataService, - uint256 amount, IGraphPayments.PaymentTypes paymentType, + address receiver, + uint256 tokens, + address dataService, uint256 tokensDataService ) external { - _graphToken().pullTokens(msg.sender, amount); + _graphToken().pullTokens(msg.sender, tokens); // Pay protocol cut - uint256 tokensProtocol = (amount * PROTOCOL_PAYMENT_CUT) / MAX_PPM; + uint256 tokensProtocol = (tokens * PROTOCOL_PAYMENT_CUT) / MAX_PPM; _graphToken().burnTokens(tokensProtocol); // Pay data service cut @@ -63,19 +64,20 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora // Get delegation cut uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, uint8(paymentType)); - uint256 tokensDelegationPool = (amount * delegationFeeCut) / MAX_PPM; + uint256 tokensDelegationPool = (tokens * delegationFeeCut) / MAX_PPM; if (tokensDelegationPool > 0) { _graphStaking().addToDelegationPool(receiver, dataService, tokensDelegationPool); } // Pay the rest to the receiver - uint256 tokensReceiver = amount - tokensProtocol - tokensDataService - tokensDelegationPool; - _graphToken().pushTokens(receiver, tokensReceiver); + uint256 tokensReceiverRemaining = tokens - tokensProtocol - tokensDataService - tokensDelegationPool; + _graphToken().pushTokens(receiver, tokensReceiverRemaining); emit GraphPaymentsCollected( msg.sender, receiver, - tokensReceiver, + dataService, + tokensReceiverRemaining, tokensDelegationPool, tokensDataService, tokensProtocol diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index d0e560b5e..f8ac5ca37 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -33,21 +33,21 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // -- Events -- - event AuthorizedCollector(address indexed sender, address indexed dataService); - event ThawCollector(address indexed sender, address indexed dataService); - event CancelThawCollector(address indexed sender, address indexed dataService); - event RevokeCollector(address indexed sender, address indexed dataService); - event Deposit(address indexed sender, address indexed receiver, uint256 amount); - event CancelThaw(address indexed sender, address indexed receiver); + event AuthorizedCollector(address indexed payer, address indexed dataService); + event ThawCollector(address indexed payer, address indexed dataService); + event CancelThawCollector(address indexed payer, address indexed dataService); + event RevokeCollector(address indexed payer, address indexed dataService); + event Deposit(address indexed payer, address indexed receiver, uint256 tokens); + event CancelThaw(address indexed payer, address indexed receiver); event Thaw( - address indexed sender, + address indexed payer, address indexed receiver, - uint256 amount, + uint256 tokens, uint256 totalAmountThawing, uint256 thawEndTimestamp ); - event Withdraw(address indexed sender, address indexed receiver, uint256 amount); - event EscrowCollected(address indexed sender, address indexed receiver, uint256 amount); + event Withdraw(address indexed payer, address indexed receiver, uint256 tokens); + event EscrowCollected(address indexed payer, address indexed receiver, uint256 tokens); // -- Errors -- @@ -61,6 +61,8 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { error GraphEscrowCollectorNotAuthorized(address sender, address dataService); error GraphEscrowCollectorInsufficientAmount(uint256 available, uint256 required); + error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); + // -- Constructor -- constructor( @@ -183,45 +185,53 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // Collect from escrow for a receiver using sender's deposit function collect( - address sender, - address receiver, // serviceProvider - address dataService, - uint256 amount, IGraphPayments.PaymentTypes paymentType, + address payer, + address receiver, + uint256 tokens, + address dataService, uint256 tokensDataService ) external { // Check if collector is authorized and has enough funds - Collector storage collector = authorizedCollectors[sender][msg.sender]; + Collector storage collector = authorizedCollectors[payer][msg.sender]; if (!collector.authorized) { - revert GraphEscrowCollectorNotAuthorized(sender, msg.sender); + revert GraphEscrowCollectorNotAuthorized(payer, msg.sender); } - if (collector.amount < amount) { - revert GraphEscrowCollectorInsufficientAmount(collector.amount, amount); + if (collector.amount < tokens) { + revert GraphEscrowCollectorInsufficientAmount(collector.amount, tokens); } // Reduce amount from approved collector - collector.amount -= amount; + collector.amount -= tokens; // Collect tokens from GraphEscrow up to amount available - EscrowAccount storage account = escrowAccounts[sender][receiver]; + EscrowAccount storage account = escrowAccounts[payer][receiver]; uint256 availableAmount = account.balance - account.amountThawing; - if (availableAmount < amount) { - revert GraphEscrowInsufficientAmount(availableAmount, amount); + if (availableAmount < tokens) { + revert GraphEscrowInsufficientAmount(availableAmount, tokens); } - account.balance -= amount; - emit EscrowCollected(sender, receiver, amount); + account.balance -= tokens; // Approve tokens so GraphPayments can pull them - _graphToken().approve(address(_graphPayments()), amount); - _graphPayments().collect(receiver, dataService, amount, paymentType, tokensDataService); + uint256 balanceBefore = _graphToken().balanceOf(address(this)); + + _graphToken().approve(address(_graphPayments()), tokens); + _graphPayments().collect(paymentType, receiver, tokens, dataService, tokensDataService); + + uint256 balanceAfter = _graphToken().balanceOf(address(this)); + if (balanceBefore - balanceAfter != tokens) { + revert PaymentsEscrowInconsistentCollection(balanceBefore, balanceAfter, tokens); + } + + emit EscrowCollected(payer, receiver, tokens); } // Get the balance of a sender-receiver pair - function getBalance(address sender, address receiver) external view returns (uint256) { - EscrowAccount storage account = escrowAccounts[sender][receiver]; + function getBalance(address payer, address receiver) external view returns (uint256) { + EscrowAccount storage account = escrowAccounts[payer][receiver]; return account.balance - account.amountThawing; } } diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol new file mode 100644 index 000000000..b5cdced84 --- /dev/null +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; +import { ITAPCollector } from "../../interfaces/ITAPCollector.sol"; + +import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; +import { PPMMath } from "../../libraries/PPMMath.sol"; + +import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; + +/** + * @title TAPVerifier + * @dev A contract for verifying receipt aggregation vouchers. + */ +contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { + using PPMMath for uint256; + + bytes32 private constant EIP712_RAV_TYPEHASH = + keccak256( + "ReceiptAggregateVoucher(address dataService, address serviceProvider,uint64 timestampNs,uint128 valueAggregate,bytes metadata)" + ); + + mapping(address dataService => mapping(address receiver => mapping(address payer => uint256 tokens))) + public tokensCollected; + + event TAPCollectorCollected( + IGraphPayments.PaymentTypes indexed paymentType, + address indexed payer, + address receiver, + uint256 tokensReceiver, + address indexed dataService, + uint256 tokensDataService + ); + + error TAPCollectorCallerNotDataService(address caller, address dataService); + error TAPVerifierInvalidSignerProof(); + error TAPCollectorInconsistentRAVTokens(uint256 tokens, uint256 tokensCollected); + + /** + * @dev Constructs a new instance of the TAPVerifier contract. + */ + constructor( + string memory eip712Name, + string memory eip712Version, + address controller + ) EIP712(eip712Name, eip712Version) GraphDirectory(controller) {} + + /** + * @notice Verify validity of a SignedRAV + * @dev Caller must be the data service the RAV was issued to. + * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. + */ + function collect(IGraphPayments.PaymentTypes paymentType, bytes memory data) external returns (uint256) { + (SignedRAV memory signedRAV, uint256 percentageDataService) = abi.decode(data, (SignedRAV, uint256)); + + if (signedRAV.rav.dataService != msg.sender) { + revert TAPCollectorCallerNotDataService(msg.sender, signedRAV.rav.dataService); + } + + address dataService = signedRAV.rav.dataService; + address payer = _recoverRAVSigner(signedRAV); + address receiver = signedRAV.rav.serviceProvider; + + uint256 tokensRAV = signedRAV.rav.valueAggregate; + uint256 tokensAlreadyCollected = tokensCollected[dataService][receiver][payer]; + if (tokensRAV < tokensAlreadyCollected) { + revert TAPCollectorInconsistentRAVTokens(tokensRAV, tokensAlreadyCollected); + } + + uint256 tokensToCollect = tokensRAV - tokensAlreadyCollected; + uint256 tokensDataService = tokensToCollect.mulPPM(percentageDataService); + + if (tokensToCollect > 0) { + _graphEscrow().collect(paymentType, payer, receiver, tokensToCollect, dataService, tokensDataService); + tokensCollected[dataService][receiver][payer] = tokensRAV; + } + + emit TAPCollectorCollected(paymentType, payer, receiver, tokensToCollect, dataService, tokensDataService); + return tokensToCollect; + } + + /** + * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). + * @param signedRAV The SignedRAV containing the RAV and its signature. + * @return The address of the signer. + * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. + */ + function recoverRAVSigner(SignedRAV calldata signedRAV) public view returns (address) { + return _recoverRAVSigner(signedRAV); + } + + /** + * @dev Computes the hash of a ReceiptAggregateVoucher (RAV). + * @param rav The RAV for which to compute the hash. + * @return The hash of the RAV. + */ + function encodeRAV(ReceiptAggregateVoucher calldata rav) public view returns (bytes32) { + return _encodeRAV(rav); + } + + function _recoverRAVSigner(SignedRAV memory __signedRAV) private view returns (address) { + bytes32 messageHash = _encodeRAV(signedRAV.rav); + return ECDSA.recover(messageHash, signedRAV.signature); + } + + function _encodeRAV(ReceiptAggregateVoucher memor _ _rav) private view returns (bytes32) { + return + _hashTypedDataV4( + keccak256( + abi.encode( + EIP712_RAV_TYPEHASH, + rav.dataService, + rav.serviceProvider, + rav.timestampNs, + rav.valueAggregate + ) + ) + ); + } +} diff --git a/packages/horizon/contracts/payments/collectors/TAPVerifier.sol b/packages/horizon/contracts/payments/collectors/TAPVerifier.sol deleted file mode 100644 index 735cc38a0..000000000 --- a/packages/horizon/contracts/payments/collectors/TAPVerifier.sol +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; - -import { ITAPVerifier } from "../../interfaces/ITAPVerifier.sol"; - -import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; - -import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; - -/** - * @title TAPVerifier - * @dev A contract for verifying receipt aggregation vouchers. - */ -contract TAPVerifier is EIP712, ITAPVerifier { - bytes32 private constant EIP712_RAV_TYPEHASH = - keccak256( - "ReceiptAggregateVoucher(address dataService, address serviceProvider,uint64 timestampNs,uint128 valueAggregate,bytes metadata)" - ); - - // The duration (in seconds) in which a signer is thawing before they can be revoked - uint256 public immutable REVOKE_SIGNER_THAWING_PERIOD; - - // Map of signer to authorized signer information - mapping(address signer => SenderAuthorization authorizedSigner) public authorizedSigners; - - /** - * @dev Emitted when a signer is authorized to sign RAVs for a sender. - */ - event AuthorizeSigner(address indexed signer, address indexed sender); - /** - * @dev Emitted when a thaw request is made for authorized signer - */ - event ThawSigner(address indexed sender, address indexed authorizedSigner, uint256 thawEndTimestamp); - - /** - * @dev Emitted when the thawing of a signer is cancelled - */ - event CancelThawSigner(address indexed sender, address indexed authorizedSigner, uint256 thawEndTimestamp); - - /** - * @dev Emitted when a authorized signer has been revoked - */ - event RevokeAuthorizedSigner(address indexed sender, address indexed authorizedSigner); - - error TAPVerifierInvalidCaller(address sender, address expected); - error TAPVerifierInvalidSignerProof(); - error TAPVerifierAlreadyAuthorized(address signer, address authorizingSender); - error TAPVerifierNotAuthorized(address signer, address sender); - error TAPVerifierNotThawing(); - error TAPVerifierStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); - - /** - * @dev Constructs a new instance of the TAPVerifier contract. - */ - constructor(string memory eip712Name, string memory eip712Version) EIP712(eip712Name, eip712Version) {} - - /** - * @dev Authorizes a signer to sign RAVs for the sender. - * @param signer Address of the authorized signer. - * @param proof The proof provided by the signer to authorize the sender, consisting of packed (chainID, proof deadline, sender address). - * @dev The proof deadline is the timestamp at which the proof expires. The proof is susceptible to replay attacks until the deadline is reached. - * @notice REVERT with error: - * - SignerAlreadyAuthorized: Signer is currently authorized for a sender - * - InvalidSignerProof: The provided signer proof is invalid - */ - function authorizeSigner(address signer, uint256 proofDeadline, bytes calldata proof) external { - if (authorizedSigners[signer].sender != address(0)) { - revert TAPVerifierAlreadyAuthorized(signer, authorizedSigners[signer].sender); - } - - _verifyAuthorizedSignerProof(proof, proofDeadline, signer); - - authorizedSigners[signer].sender = msg.sender; - authorizedSigners[signer].thawEndTimestamp = 0; - emit AuthorizeSigner(signer, msg.sender); - } - - /** - * @dev Starts thawing a signer to be removed from the authorized signers list. - * @param signer Address of the signer to remove. - * @notice WARNING: Thawing a signer alerts receivers that signatures from that signer will soon be deemed invalid. - * Receivers without existing signed receipts or RAVs from this signer should treat them as unauthorized. - * Those with existing signed documents from this signer should work towards settling their engagements. - * Once a signer is thawed, they should be viewed as revoked regardless of their revocation status. - * @notice REVERT with error: - * - SignerNotAuthorizedBySender: The provided signer is either not authorized or - * authorized by a different sender - */ - function thawSigner(address signer) external { - SenderAuthorization storage authorization = authorizedSigners[signer]; - - if (authorization.sender != msg.sender) { - revert TAPVerifierNotAuthorized(signer, authorizedSigners[signer].sender); - } - - authorization.thawEndTimestamp = block.timestamp + REVOKE_SIGNER_THAWING_PERIOD; - emit ThawSigner(authorization.sender, signer, authorization.thawEndTimestamp); - } - - /** - * @dev Stops thawing a signer. - * @param signer Address of the signer to stop thawing. - * @notice REVERT with error: - * - SignerNotAuthorizedBySender: The provided signer is either not authorized or - * authorized by a different sender - */ - function cancelThawSigner(address signer) external { - SenderAuthorization storage authorization = authorizedSigners[signer]; - - if (authorization.sender != msg.sender) { - revert TAPVerifierNotAuthorized(signer, authorizedSigners[signer].sender); - } - - authorization.thawEndTimestamp = 0; - emit CancelThawSigner(authorization.sender, signer, authorization.thawEndTimestamp); - } - - /** - * @dev Revokes a signer from the authorized signers list if thawed. - * @param signer Address of the signer to remove. - * @notice REVERT with error: - * - SignerNotAuthorizedBySender: The provided signer is either not authorized or - * authorized by a different sender - * - SignerNotThawing: No thaw was initiated for the provided signer - * - SignerStillThawing: ThawEndTimestamp has not been reached - * for provided signer - */ - function revokeAuthorizedSigner(address signer) external { - SenderAuthorization storage authorization = authorizedSigners[signer]; - - if (authorization.sender != msg.sender) { - revert TAPVerifierNotAuthorized(signer, authorizedSigners[signer].sender); - } - - if (authorization.thawEndTimestamp == 0) { - revert TAPVerifierNotThawing(); - } - - if (authorization.thawEndTimestamp > block.timestamp) { - revert TAPVerifierStillThawing({ - currentTimestamp: block.timestamp, - thawEndTimestamp: authorization.thawEndTimestamp - }); - } - - delete authorizedSigners[signer]; - emit RevokeAuthorizedSigner(authorization.sender, signer); - } - - /** - * @notice Verify validity of a SignedRAV - * @dev Caller must be the data service the RAV was issued to. - * @param signedRAV The SignedRAV containing the RAV and its signature. - * @return The address of the signer. - * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. - */ - function verify(SignedRAV calldata signedRAV) external view returns (address) { - if (signedRAV.rav.dataService != msg.sender) { - revert TAPVerifierInvalidCaller(msg.sender, signedRAV.rav.dataService); - } - return recover(signedRAV); - } - - /** - * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). - * @param signedRAV The SignedRAV containing the RAV and its signature. - * @return The address of the signer. - * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. - */ - function recover(SignedRAV calldata signedRAV) public view returns (address) { - bytes32 messageHash = encodeRAV(signedRAV.rav); - return ECDSA.recover(messageHash, signedRAV.signature); - } - - /** - * @dev Computes the hash of a ReceiptAggregateVoucher (RAV). - * @param rav The RAV for which to compute the hash. - * @return The hash of the RAV. - */ - function encodeRAV(ReceiptAggregateVoucher calldata rav) public view returns (bytes32) { - return - _hashTypedDataV4( - keccak256( - abi.encode( - EIP712_RAV_TYPEHASH, - rav.dataService, - rav.serviceProvider, - rav.timestampNs, - rav.valueAggregate - ) - ) - ); - } - - /** - * @dev Verifies a proof that authorizes the sender to authorize the signer. - * @param _proof The proof provided by the signer to authorize the sender. - * @param _signer The address of the signer being authorized. - * @notice REVERT with error: - * - InvalidSignerProof: If the given proof is not valid - */ - function _verifyAuthorizedSignerProof(bytes calldata _proof, uint256 _proofDeadline, address _signer) private view { - // Verify that the proof deadline has not passed - if (block.timestamp > _proofDeadline) { - revert TAPVerifierInvalidSignerProof(); - } - - // Generate the hash of the sender's address - bytes32 messageHash = keccak256(abi.encodePacked(block.chainid, _proofDeadline, msg.sender)); - - // Generate the digest to be signed by the signer - bytes32 digest = MessageHashUtils.toEthSignedMessageHash(messageHash); - - // Verify that the recovered signer matches the expected signer - if (ECDSA.recover(digest, _proof) != _signer) { - revert TAPVerifierInvalidSignerProof(); - } - } -} diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 604e1b4ee..1f2b733f6 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -21,7 +21,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { uint256 indexerPreviousBalance = token.balanceOf(users.indexer); vm.prank(users.verifier); - escrow.collect(users.gateway, users.indexer, subgraphDataServiceAddress, 100 ether, IGraphPayments.PaymentTypes.IndexingFee, 3 ether); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, 100 ether, subgraphDataServiceAddress, 3 ether); uint256 indexerBalance = token.balanceOf(users.indexer); assertEq(indexerBalance - indexerPreviousBalance, 86 ether); @@ -35,7 +35,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { uint256 dataServiceCut = 30000; // 3% bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); vm.expectRevert(expectedError); - escrow.collect(users.gateway, indexer, subgraphDataServiceAddress, amount, IGraphPayments.PaymentTypes.IndexingFee, dataServiceCut); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, indexer, amount, subgraphDataServiceAddress, dataServiceCut); vm.stopPrank(); } @@ -55,7 +55,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { uint256 dataServiceCut = 30 ether; bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", 100 ether, 1000 ether); vm.expectRevert(expectedError); - escrow.collect(users.gateway, indexer, subgraphDataServiceAddress, 1000 ether, IGraphPayments.PaymentTypes.IndexingFee, dataServiceCut); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, indexer, 1000 ether, subgraphDataServiceAddress, dataServiceCut); vm.stopPrank(); } @@ -69,7 +69,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { vm.prank(users.verifier); bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", 100 ether, 200 ether); vm.expectRevert(expectedError); - escrow.collect(users.gateway, users.indexer, subgraphDataServiceAddress, 200 ether, IGraphPayments.PaymentTypes.IndexingFee, 3 ether); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, 200 ether, subgraphDataServiceAddress, 3 ether); vm.stopPrank(); } } \ No newline at end of file diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 73f8f431b..4bf00ff8d 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -25,7 +25,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { // Collect payments through GraphPayments uint256 dataServiceCut = 30 ether; // 3% uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - payments.collect(users.indexer, subgraphDataServiceAddress, amount, IGraphPayments.PaymentTypes.IndexingFee, dataServiceCut); + payments.collect(IGraphPayments.PaymentTypes.IndexingFee, users.indexer, amount, subgraphDataServiceAddress, dataServiceCut); vm.stopPrank(); uint256 indexerBalance = token.balanceOf(users.indexer); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index e7484247b..d27c2093c 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.24; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; -import { ITAPVerifier } from "@graphprotocol/horizon/contracts/interfaces/ITAPVerifier.sol"; +import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; @@ -35,18 +35,16 @@ contract SubgraphService is event QueryFeesCollected( address serviceProvider, - address payer, uint256 tokensCollected, uint256 tokensCurators, uint256 tokensSubgraphService ); error SubgraphServiceEmptyUrl(); - error SubgraphServiceInconsistentRAVTokens(uint256 tokens, uint256 tokensCollected); error SubgraphServiceInvalidPaymentType(IGraphPayments.PaymentTypes feeType); error SubgraphServiceIndexerAlreadyRegistered(); error SubgraphServiceIndexerNotRegistered(address indexer); - error SubgraphServiceInconsistentCollection(uint256 tokensExpected, uint256 tokensCollected); + error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); modifier onlyRegisteredIndexer(address indexer) { if (indexers[indexer].registeredAt == 0) { @@ -199,55 +197,44 @@ contract SubgraphService is } function _collectQueryFees(bytes memory _data) private returns (uint256 feesCollected) { - ITAPVerifier.SignedRAV memory signedRav = abi.decode(_data, (ITAPVerifier.SignedRAV)); + ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); address indexer = signedRav.rav.serviceProvider; address allocationId = abi.decode(signedRav.rav.metadata, (address)); + bytes32 subgraphDeploymentId = allocations.get(allocationId).subgraphDeploymentId; // release expired stake claims _releaseStake(IGraphPayments.PaymentTypes.QueryFee, indexer, 0); - // validate RAV and calculate tokens to collect - address payer = TAP_VERIFIER.verify(signedRav); - uint256 tokens = signedRav.rav.valueAggregate; - uint256 tokensAlreadyCollected = tokensCollected[indexer][payer]; - if (tokens <= tokensAlreadyCollected) { - revert SubgraphServiceInconsistentRAVTokens(tokens, tokensAlreadyCollected); + // Collect from GraphPayments + PaymentCuts memory queryFeePaymentCuts = _getQueryFeePaymentCuts(subgraphDeploymentId); + uint256 percentageTotalCut = queryFeePaymentCuts.percentageServiceCut + + queryFeePaymentCuts.percentageCurationCut; + + uint256 balanceBefore = _graphToken().balanceOf(address(this)); + uint256 tokensCollected = TAP_COLLECTOR.collect( + IGraphPayments.PaymentTypes.QueryFee, + abi.encode(signedRav, percentageTotalCut) + ); + uint256 tokensDataService = tokensCollected.mulPPM(percentageTotalCut); + uint256 balanceAfter = _graphToken().balanceOf(address(this)); + if (balanceAfter - balanceBefore != tokensDataService) { + revert SubgraphServiceInconsistentCollection(balanceBefore, balanceAfter, tokensDataService); } - uint256 tokensToCollect = tokens - tokensAlreadyCollected; + uint256 tokensCurators = 0; uint256 tokensSubgraphService = 0; - - if (tokensToCollect > 0) { + if (tokensCollected > 0) { // lock stake as economic security for fees - // block scope to avoid 'stack too deep' error - { - uint256 tokensToLock = tokensToCollect * stakeToFeesRatio; - uint256 unlockTimestamp = block.timestamp + DISPUTE_MANAGER.getDisputePeriod(); - _lockStake(IGraphPayments.PaymentTypes.QueryFee, indexer, tokensToLock, unlockTimestamp); - } - - // get subgraph deployment id - reverts if allocation is not found - bytes32 subgraphDeploymentId = allocations.get(allocationId).subgraphDeploymentId; + uint256 tokensToLock = tokensCollected * stakeToFeesRatio; + uint256 unlockTimestamp = block.timestamp + DISPUTE_MANAGER.getDisputePeriod(); + _lockStake(IGraphPayments.PaymentTypes.QueryFee, indexer, tokensToLock, unlockTimestamp); // calculate service and curator cuts - // TODO: note we don't let curation cut round down to zero - PaymentFee memory feePercentages = _getQueryFeesPaymentFees(subgraphDeploymentId); - tokensSubgraphService = tokensToCollect.mulPPM(feePercentages.servicePercentage); - tokensCurators = tokensToCollect.mulPPMRoundUp(feePercentages.curationPercentage); - uint256 totalCut = tokensSubgraphService + tokensCurators; - - // collect fees - uint256 balanceBefore = _graphToken().balanceOf(address(this)); - _graphPayments().collect(payer, indexer, tokensToCollect, IGraphPayments.PaymentTypes.QueryFee, totalCut); - uint256 balanceAfter = _graphToken().balanceOf(address(this)); - if (balanceBefore + totalCut != balanceAfter) { - revert SubgraphServiceInconsistentCollection(balanceBefore + totalCut, balanceAfter); - } - tokensCollected[indexer][payer] = tokens; + tokensCurators = tokensCollected.mulPPMRoundUp(queryFeePaymentCuts.percentageCurationCut); + tokensSubgraphService = tokensDataService - tokensCurators; - // distribute curation cut to curators if (tokensCurators > 0) { - // we are about to change subgraph signal so we take rewards snapshot + // curation collection changes subgraph signal so we take rewards snapshot _graphRewardsManager().onSubgraphSignalUpdate(subgraphDeploymentId); // Send GRT and bookkeep by calling collect() @@ -256,18 +243,18 @@ contract SubgraphService is } } - emit QueryFeesCollected(indexer, payer, tokensToCollect, tokensCurators, tokensSubgraphService); - return tokensToCollect; + emit QueryFeesCollected(indexer, tokensCollected, tokensCurators, tokensSubgraphService); + return tokensCollected; } - function _getQueryFeesPaymentFees(bytes32 _subgraphDeploymentId) private view returns (PaymentFee memory) { - PaymentFee memory feePercentages = paymentFees[IGraphPayments.PaymentTypes.QueryFee]; + function _getQueryFeePaymentCuts(bytes32 _subgraphDeploymentId) private view returns (PaymentCuts memory) { + PaymentCuts memory queryFeePaymentCuts = paymentCuts[IGraphPayments.PaymentTypes.QueryFee]; // Only pay curation fees if the subgraph is curated if (!CURATION.isCurated(_subgraphDeploymentId)) { - feePercentages.curationPercentage = 0; + queryFeePaymentCuts.percentageCurationCut = 0; } - return feePercentages; + return queryFeePaymentCuts; } } diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index c67702428..671279989 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -13,7 +13,5 @@ abstract contract SubgraphServiceV1Storage { uint256 public stakeToFeesRatio; /// @notice The fees cut taken by the subgraph service - mapping(IGraphPayments.PaymentTypes paymentType => ISubgraphService.PaymentFee paymentFees) public paymentFees; - - mapping(address indexer => mapping(address payer => uint256 tokens)) public tokensCollected; + mapping(IGraphPayments.PaymentTypes paymentType => ISubgraphService.PaymentCuts paymentCuts) public paymentCuts; } diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 17dd7019c..4e395fc0b 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -13,9 +13,9 @@ interface ISubgraphService is IDataServiceFees { string geoHash; } - struct PaymentFee { - uint128 servicePercentage; - uint128 curationPercentage; + struct PaymentCuts { + uint128 percentageServiceCut; + uint128 percentageCurationCut; } function resizeAllocation(address indexer, address allocationId, uint256 tokens) external; diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index bc452f072..f6f9253ab 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { ITAPVerifier } from "@graphprotocol/horizon/contracts/interfaces/ITAPVerifier.sol"; +import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { IDisputeManager } from "../interfaces/IDisputeManager.sol"; import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; abstract contract Directory { - ITAPVerifier public immutable TAP_VERIFIER; + ITAPCollector public immutable TAP_COLLECTOR; IDisputeManager public immutable DISPUTE_MANAGER; ISubgraphService public immutable SUBGRAPH_SERVICE; ICuration public immutable CURATION; @@ -29,7 +29,7 @@ abstract contract Directory { constructor(address subgraphService, address tapVerifier, address disputeManager, address curation) { SUBGRAPH_SERVICE = ISubgraphService(subgraphService); - TAP_VERIFIER = ITAPVerifier(tapVerifier); + TAP_COLLECTOR = ITAPCollector(tapVerifier); DISPUTE_MANAGER = IDisputeManager(disputeManager); CURATION = ICuration(curation); From 58db521f83c4e1203095bddaa9095fc39db82ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 22 May 2024 12:21:47 -0300 Subject: [PATCH 038/277] feat: add bridge escrow and graph proxy admin to graph directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/gateway/IBridgeEscrow.sol | 26 +++++++ .../contracts/upgrades/IGraphProxyAdmin.sol | 10 +++ .../contracts/data-service/GraphDirectory.sol | 78 ++++++++++++------- .../contracts/payments/GraphPayments.sol | 1 - .../payments/collectors/TAPCollector.sol | 26 ++++--- .../staking/StakingBackwardsCompatibility.sol | 2 - 6 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 packages/contracts/contracts/gateway/IBridgeEscrow.sol create mode 100644 packages/contracts/contracts/upgrades/IGraphProxyAdmin.sol diff --git a/packages/contracts/contracts/gateway/IBridgeEscrow.sol b/packages/contracts/contracts/gateway/IBridgeEscrow.sol new file mode 100644 index 000000000..733288e9c --- /dev/null +++ b/packages/contracts/contracts/gateway/IBridgeEscrow.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +/** + * @title IBridgeEscrow + */ +interface IBridgeEscrow { + /** + * @notice Initialize the BridgeEscrow contract. + * @param _controller Address of the Controller that manages this contract + */ + function initialize(address _controller) external; + + /** + * @notice Approve a spender (i.e. a bridge that manages the GRT funds held by the escrow) + * @param _spender Address of the spender that will be approved + */ + function approveAll(address _spender) external; + + /** + * @notice Revoke a spender (i.e. a bridge that will no longer manage the GRT funds held by the escrow) + * @param _spender Address of the spender that will be revoked + */ + function revokeAll(address _spender) external; +} diff --git a/packages/contracts/contracts/upgrades/IGraphProxyAdmin.sol b/packages/contracts/contracts/upgrades/IGraphProxyAdmin.sol new file mode 100644 index 000000000..2abf4517d --- /dev/null +++ b/packages/contracts/contracts/upgrades/IGraphProxyAdmin.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +/** + * @title IGraphProxyAdmin + * @dev Empty interface to allow the GraphProxyAdmin contract to be used + * in the GraphDirectory contract. + */ +interface IGraphProxyAdmin {} diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index 24cfa14e0..f05d9db66 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -2,50 +2,58 @@ pragma solidity 0.8.24; -import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; -import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; import { ITokenGateway } from "@graphprotocol/contracts/contracts/arbitrum/ITokenGateway.sol"; +import { IBridgeEscrow } from "@graphprotocol/contracts/contracts/gateway/IBridgeEscrow.sol"; +import { IGraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/IGraphProxyAdmin.sol"; + +import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; /** * @title GraphDirectory contract * @notice This contract is meant to be inherited by other contracts that - * need to keep track of the addresses of the core Graph Horizon contracts. + * need to keep track of the addresses in Graph Horizon contracts. * It fetches the addresses from the Controller supplied during construction, * and uses immutable variables to minimize gas costs. */ abstract contract GraphDirectory { - IController private immutable GRAPH_CONTROLLER; - // Graph Horizon contracts IGraphToken private immutable GRAPH_TOKEN; IHorizonStaking private immutable GRAPH_STAKING; IGraphPayments private immutable GRAPH_PAYMENTS; - IPaymentsEscrow private immutable GRAPH_ESCROW; + IPaymentsEscrow private immutable GRAPH_PAYMENTS_ESCROW; - // Legacy Graph contracts - // Required for StakingBackwardCompatibility - // TODO: remove these once StakingBackwardCompatibility is removed + // Graph periphery contracts + IController private immutable GRAPH_CONTROLLER; IEpochManager private immutable GRAPH_EPOCH_MANAGER; IRewardsManager private immutable GRAPH_REWARDS_MANAGER; - ICuration private immutable GRAPH_CURATION; ITokenGateway private immutable GRAPH_TOKEN_GATEWAY; + IBridgeEscrow private immutable GRAPH_BRIDGE_ESCROW; + IGraphProxyAdmin private immutable GRAPH_PROXY_ADMIN; + + // Legacy Graph contracts - required for StakingBackwardCompatibility + // TODO: remove these once StakingBackwardCompatibility is removed + ICuration private immutable GRAPH_CURATION; event GraphDirectoryInitialized( - IController graphController, IGraphToken graphToken, IHorizonStaking graphStaking, IGraphPayments graphPayments, IPaymentsEscrow graphEscrow, + IController graphController, IEpochManager graphEpochManager, IRewardsManager graphRewardsManager, - ICuration graphCuration, - ITokenGateway graphTokenGateway + ITokenGateway graphTokenGateway, + IBridgeEscrow graphBridgeEscrow, + IGraphProxyAdmin graphProxyAdmin, + ICuration graphCuration ); error GraphDirectoryInvalidZeroAddress(); @@ -59,29 +67,29 @@ abstract contract GraphDirectory { GRAPH_TOKEN = IGraphToken(_getContractFromController("GraphToken")); GRAPH_STAKING = IHorizonStaking(_getContractFromController("Staking")); GRAPH_PAYMENTS = IGraphPayments(_getContractFromController("GraphPayments")); - GRAPH_ESCROW = IPaymentsEscrow(_getContractFromController("PaymentsEscrow")); + GRAPH_PAYMENTS_ESCROW = IPaymentsEscrow(_getContractFromController("PaymentsEscrow")); GRAPH_EPOCH_MANAGER = IEpochManager(_getContractFromController("EpochManager")); GRAPH_REWARDS_MANAGER = IRewardsManager(_getContractFromController("RewardsManager")); - GRAPH_CURATION = ICuration(_getContractFromController("Curation")); GRAPH_TOKEN_GATEWAY = ITokenGateway(_getContractFromController("GraphTokenGateway")); + GRAPH_BRIDGE_ESCROW = IBridgeEscrow(_getContractFromController("BridgeEscrow")); + GRAPH_PROXY_ADMIN = IGraphProxyAdmin(_getContractFromController("GraphProxyAdmin")); + GRAPH_CURATION = ICuration(_getContractFromController("Curation")); emit GraphDirectoryInitialized( - GRAPH_CONTROLLER, GRAPH_TOKEN, GRAPH_STAKING, GRAPH_PAYMENTS, - GRAPH_ESCROW, + GRAPH_PAYMENTS_ESCROW, + GRAPH_CONTROLLER, GRAPH_EPOCH_MANAGER, GRAPH_REWARDS_MANAGER, - GRAPH_CURATION, - GRAPH_TOKEN_GATEWAY + GRAPH_TOKEN_GATEWAY, + GRAPH_BRIDGE_ESCROW, + GRAPH_PROXY_ADMIN, + GRAPH_CURATION ); } - function _graphController() internal view returns (IController) { - return GRAPH_CONTROLLER; - } - function _graphToken() internal view returns (IGraphToken) { return GRAPH_TOKEN; } @@ -94,8 +102,12 @@ abstract contract GraphDirectory { return GRAPH_PAYMENTS; } - function _graphEscrow() internal view returns (IPaymentsEscrow) { - return GRAPH_ESCROW; + function _graphPaymentsEscrow() internal view returns (IPaymentsEscrow) { + return GRAPH_PAYMENTS_ESCROW; + } + + function _graphController() internal view returns (IController) { + return GRAPH_CONTROLLER; } function _graphEpochManager() internal view returns (IEpochManager) { @@ -106,14 +118,22 @@ abstract contract GraphDirectory { return GRAPH_REWARDS_MANAGER; } - function _graphCuration() internal view returns (ICuration) { - return GRAPH_CURATION; - } - function _graphTokenGateway() internal view returns (ITokenGateway) { return GRAPH_TOKEN_GATEWAY; } + function _graphBridgeEscrow() internal view returns (IBridgeEscrow) { + return GRAPH_BRIDGE_ESCROW; + } + + function _graphProxyAdmin() internal view returns (IGraphProxyAdmin) { + return GRAPH_PROXY_ADMIN; + } + + function _graphCuration() internal view returns (ICuration) { + return GRAPH_CURATION; + } + function _getContractFromController(bytes memory _contractName) private view returns (address) { address contractAddress = GRAPH_CONTROLLER.getContractProxy(keccak256(_contractName)); if (contractAddress == address(0)) { diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 7644d68cf..2ba8f8dc8 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.24; import { IGraphToken } from "../interfaces/IGraphToken.sol"; -import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index b5cdced84..f0fb31077 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -9,7 +9,6 @@ import { PPMMath } from "../../libraries/PPMMath.sol"; import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; /** * @title TAPVerifier @@ -74,7 +73,14 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { uint256 tokensDataService = tokensToCollect.mulPPM(percentageDataService); if (tokensToCollect > 0) { - _graphEscrow().collect(paymentType, payer, receiver, tokensToCollect, dataService, tokensDataService); + _graphPaymentsEscrow().collect( + paymentType, + payer, + receiver, + tokensToCollect, + dataService, + tokensDataService + ); tokensCollected[dataService][receiver][payer] = tokensRAV; } @@ -101,21 +107,21 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { return _encodeRAV(rav); } - function _recoverRAVSigner(SignedRAV memory __signedRAV) private view returns (address) { - bytes32 messageHash = _encodeRAV(signedRAV.rav); - return ECDSA.recover(messageHash, signedRAV.signature); + function _recoverRAVSigner(SignedRAV memory _signedRAV) private view returns (address) { + bytes32 messageHash = _encodeRAV(_signedRAV.rav); + return ECDSA.recover(messageHash, _signedRAV.signature); } - function _encodeRAV(ReceiptAggregateVoucher memor _ _rav) private view returns (bytes32) { + function _encodeRAV(ReceiptAggregateVoucher memory _rav) private view returns (bytes32) { return _hashTypedDataV4( keccak256( abi.encode( EIP712_RAV_TYPEHASH, - rav.dataService, - rav.serviceProvider, - rav.timestampNs, - rav.valueAggregate + _rav.dataService, + _rav.serviceProvider, + _rav.timestampNs, + _rav.valueAggregate ) ) ); diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index a570242f4..9928a88d5 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -3,8 +3,6 @@ pragma solidity 0.8.24; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; -import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; -import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; From 3d11376234c63044911410ee70d196b96bbfa453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 22 May 2024 14:33:17 -0300 Subject: [PATCH 039/277] chore: subgraph service directory revamp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/SubgraphService.sol | 16 ++++----- .../contracts/utilities/Directory.sol | 34 ++++++++++++++----- packages/subgraph-service/package.json | 2 +- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index d27c2093c..261dd8805 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -157,7 +157,7 @@ contract SubgraphService is function slash(address indexer, bytes calldata data) external override onlyDisputeManager whenNotPaused { (uint256 tokens, uint256 reward) = abi.decode(data, (uint256, uint256)); - _graphStaking().slash(indexer, tokens, reward, address(DISPUTE_MANAGER)); + _graphStaking().slash(indexer, tokens, reward, address(_disputeManager())); emit ServiceProviderSlashed(indexer, tokens); } @@ -187,12 +187,12 @@ contract SubgraphService is // -- Data service parameter getters -- function _getThawingPeriodRange() internal view override returns (uint64 min, uint64 max) { - uint64 disputePeriod = DISPUTE_MANAGER.getDisputePeriod(); + uint64 disputePeriod = _disputeManager().getDisputePeriod(); return (disputePeriod, type(uint64).max); } function _getVerifierCutRange() internal view override returns (uint32 min, uint32 max) { - uint32 verifierCut = DISPUTE_MANAGER.getVerifierCut(); + uint32 verifierCut = _disputeManager().getVerifierCut(); return (verifierCut, type(uint32).max); } @@ -211,7 +211,7 @@ contract SubgraphService is queryFeePaymentCuts.percentageCurationCut; uint256 balanceBefore = _graphToken().balanceOf(address(this)); - uint256 tokensCollected = TAP_COLLECTOR.collect( + uint256 tokensCollected = _tapCollector().collect( IGraphPayments.PaymentTypes.QueryFee, abi.encode(signedRav, percentageTotalCut) ); @@ -226,7 +226,7 @@ contract SubgraphService is if (tokensCollected > 0) { // lock stake as economic security for fees uint256 tokensToLock = tokensCollected * stakeToFeesRatio; - uint256 unlockTimestamp = block.timestamp + DISPUTE_MANAGER.getDisputePeriod(); + uint256 unlockTimestamp = block.timestamp + _disputeManager().getDisputePeriod(); _lockStake(IGraphPayments.PaymentTypes.QueryFee, indexer, tokensToLock, unlockTimestamp); // calculate service and curator cuts @@ -238,8 +238,8 @@ contract SubgraphService is _graphRewardsManager().onSubgraphSignalUpdate(subgraphDeploymentId); // Send GRT and bookkeep by calling collect() - _graphToken().transfer(address(CURATION), tokensCurators); - CURATION.collect(subgraphDeploymentId, tokensCurators); + _graphToken().transfer(address(_curation()), tokensCurators); + _curation().collect(subgraphDeploymentId, tokensCurators); } } @@ -251,7 +251,7 @@ contract SubgraphService is PaymentCuts memory queryFeePaymentCuts = paymentCuts[IGraphPayments.PaymentTypes.QueryFee]; // Only pay curation fees if the subgraph is curated - if (!CURATION.isCurated(_subgraphDeploymentId)) { + if (!_curation().isCurated(_subgraphDeploymentId)) { queryFeePaymentCuts.percentageCurationCut = 0; } diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index f6f9253ab..f4e756cf6 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -1,21 +1,21 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { IDisputeManager } from "../interfaces/IDisputeManager.sol"; import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; +import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; abstract contract Directory { - ITAPCollector public immutable TAP_COLLECTOR; - IDisputeManager public immutable DISPUTE_MANAGER; - ISubgraphService public immutable SUBGRAPH_SERVICE; - ICuration public immutable CURATION; + ISubgraphService private immutable SUBGRAPH_SERVICE; + IDisputeManager private immutable DISPUTE_MANAGER; + ITAPCollector private immutable TAP_COLLECTOR; + ICuration private immutable CURATION; event SubgraphServiceDirectoryInitialized( address subgraphService, - address tapVerifier, address disputeManager, + address tapCollector, address curation ); error DirectoryNotDisputeManager(address caller, address disputeManager); @@ -27,12 +27,28 @@ abstract contract Directory { _; } - constructor(address subgraphService, address tapVerifier, address disputeManager, address curation) { + constructor(address subgraphService, address disputeManager, address tapCollector, address curation) { SUBGRAPH_SERVICE = ISubgraphService(subgraphService); - TAP_COLLECTOR = ITAPCollector(tapVerifier); DISPUTE_MANAGER = IDisputeManager(disputeManager); + TAP_COLLECTOR = ITAPCollector(tapCollector); CURATION = ICuration(curation); - emit SubgraphServiceDirectoryInitialized(subgraphService, tapVerifier, disputeManager, curation); + emit SubgraphServiceDirectoryInitialized(subgraphService, disputeManager, tapCollector, curation); + } + + function _subgraphService() internal view returns (ISubgraphService) { + return SUBGRAPH_SERVICE; + } + + function _disputeManager() internal view returns (IDisputeManager) { + return DISPUTE_MANAGER; + } + + function _tapCollector() internal view returns (ITAPCollector) { + return TAP_COLLECTOR; + } + + function _curation() internal view returns (ICuration) { + return CURATION; } } diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index 8ad66358e..8df36e35f 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -10,7 +10,7 @@ "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", "build": "forge build && hardhat compile", - "test": "forge test && hardhat test" + "test": "forge test -vvv && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", From 72d679c969dea66b053f784d0fb1e00212db348d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 22 May 2024 15:05:33 -0300 Subject: [PATCH 040/277] feat: update rewards manager to add allowlist for taking rewards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/rewards/IRewardsIssuer.sol | 20 ++++++++ .../contracts/rewards/IRewardsManager.sol | 2 + .../contracts/rewards/RewardsManager.sol | 46 +++++++++++++------ .../rewards/RewardsManagerStorage.sol | 5 ++ .../staking/StakingBackwardsCompatibility.sol | 22 ++++++++- .../contracts/SubgraphService.sol | 9 ++++ .../test/mocks/MockRewardsManager.sol | 2 + 7 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 packages/contracts/contracts/rewards/IRewardsIssuer.sol diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol new file mode 100644 index 000000000..bf2f8c430 --- /dev/null +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity >=0.6.12 <0.9.0; + +interface IRewardsIssuer { + /** + * @dev Get allocation data to calculate rewards issuance + * @param allocationId The allocation ID + * @return indexer The indexer address + * @return subgraphDeploymentID Subgraph deployment id for the allocation + * @return tokens Amount of allocated tokens + * @return accRewardsPerAllocatedToken Rewards snapshot + */ + function getAllocationData( + address allocationId + ) + external + view + returns (address indexer, bytes32 subgraphDeploymentID, uint256 tokens, uint256 accRewardsPerAllocatedToken); +} diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index 4266a8635..2d2bd4003 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -19,6 +19,8 @@ interface IRewardsManager { function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external; + function setRewardsIssuer(address _rewardsIssuer, bool _allowed) external; + // -- Denylist -- function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external; diff --git a/packages/contracts/contracts/rewards/RewardsManager.sol b/packages/contracts/contracts/rewards/RewardsManager.sol index 03cadacb0..41c79e861 100644 --- a/packages/contracts/contracts/rewards/RewardsManager.sol +++ b/packages/contracts/contracts/rewards/RewardsManager.sol @@ -10,6 +10,7 @@ import "../staking/libs/MathUtils.sol"; import "./RewardsManagerStorage.sol"; import "./IRewardsManager.sol"; +import { IRewardsIssuer } from "./IRewardsIssuer.sol"; /** * @title Rewards Manager Contract @@ -28,7 +29,7 @@ import "./IRewardsManager.sol"; * These functions may overestimate the actual rewards due to changes in the total supply * until the actual takeRewards function is called. */ -contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsManager { +contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsManager { using SafeMath for uint256; uint256 private constant FIXED_POINT_SCALING_FACTOR = 1e18; @@ -38,18 +39,23 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa /** * @dev Emitted when rewards are assigned to an indexer. */ - event RewardsAssigned(address indexed indexer, address indexed allocationID, uint256 epoch, uint256 amount); + event RewardsAssigned(address indexed indexer, address indexed allocationID, uint256 amount); /** * @dev Emitted when rewards are denied to an indexer. */ - event RewardsDenied(address indexed indexer, address indexed allocationID, uint256 epoch); + event RewardsDenied(address indexed indexer, address indexed allocationID); /** * @dev Emitted when a subgraph is denied for claiming rewards. */ event RewardsDenylistUpdated(bytes32 indexed subgraphDeploymentID, uint256 sinceBlock); + /** + * @dev Emitted when a rewards issuer is updated. + */ + event RewardsIssuerSet(address indexed rewardsIssuer, bool allowed); + // -- Modifiers -- modifier onlySubgraphAvailabilityOracle() { @@ -115,6 +121,11 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa emit ParameterUpdated("minimumSubgraphSignal"); } + function setRewardsIssuer(address _rewardsIssuer, bool _allowed) external override onlyGovernor { + rewardsIssuers[_rewardsIssuer] = _allowed; + emit RewardsIssuerSet(_rewardsIssuer, _allowed); + } + // -- Denylist -- /** @@ -349,29 +360,34 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa * @return Assigned rewards amount */ function takeRewards(address _allocationID) external override returns (uint256) { - // Only Staking contract is authorized as caller - IStaking staking = staking(); - require(msg.sender == address(staking), "Caller must be the staking contract"); + address rewardsIssuer = msg.sender; + require(rewardsIssuers[rewardsIssuer], "Caller must be a rewards issuer"); + + ( + address indexer, + bytes32 subgraphDeploymentID, + uint256 tokens, + uint256 accRewardsPerAllocatedToken + ) = IRewardsIssuer(rewardsIssuer).getAllocationData(_allocationID); - IStaking.Allocation memory alloc = staking.getAllocation(_allocationID); - uint256 accRewardsPerAllocatedToken = onSubgraphAllocationUpdate(alloc.subgraphDeploymentID); + uint256 updatedAccRewardsPerAllocatedToken = onSubgraphAllocationUpdate(subgraphDeploymentID); // Do not do rewards on denied subgraph deployments ID - if (isDenied(alloc.subgraphDeploymentID)) { - emit RewardsDenied(alloc.indexer, _allocationID, alloc.closedAtEpoch); + if (isDenied(subgraphDeploymentID)) { + emit RewardsDenied(indexer, _allocationID); return 0; } // Calculate rewards accrued by this allocation - uint256 rewards = _calcRewards(alloc.tokens, alloc.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken); + uint256 rewards = _calcRewards(tokens, accRewardsPerAllocatedToken, updatedAccRewardsPerAllocatedToken); if (rewards > 0) { - // Mint directly to staking contract for the reward amount - // The staking contract will do bookkeeping of the reward and + // Mint directly to rewards issuer for the reward amount + // The rewards issuer contract will do bookkeeping of the reward and // assign in proportion to each stakeholder incentive - graphToken().mint(address(staking), rewards); + graphToken().mint(rewardsIssuer, rewards); } - emit RewardsAssigned(alloc.indexer, _allocationID, alloc.closedAtEpoch, rewards); + emit RewardsAssigned(indexer, _allocationID, rewards); return rewards; } diff --git a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol index 72dbda373..afcd98e43 100644 --- a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol +++ b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol @@ -36,3 +36,8 @@ contract RewardsManagerV4Storage is RewardsManagerV3Storage { // GRT issued for indexer rewards per block uint256 public issuancePerBlock; } + +contract RewardsManagerV5Storage is RewardsManagerV4Storage { + // List of addresses that are allowed to issue rewards + mapping(address => bool) public rewardsIssuers; +} diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 9928a88d5..737fd8d5f 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; +import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; @@ -24,7 +25,12 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * Note that this contract delegates part of its functionality to a StakingExtension contract. * This is due to the 24kB contract size limit on Ethereum. */ -abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Storage, IStakingBackwardsCompatibility { +abstract contract StakingBackwardsCompatibility is + Managed, + HorizonStakingV1Storage, + IRewardsIssuer, + IStakingBackwardsCompatibility +{ using TokenUtils for IGraphToken; /// @dev 100% in parts per million @@ -184,6 +190,20 @@ abstract contract StakingBackwardsCompatibility is Managed, HorizonStakingV1Stor return __DEPRECATED_allocations[allocationID]; } + /** + * @notice Return allocation data by ID. + * @dev To be called by the Rewards Manager to calculate rewards issuance. + * @dev TODO: Remove after Horizon transition period + * @param allocationID Address used as allocation identifier + * @return Allocation data + */ + function getAllocationData( + address allocationID + ) external view override returns (address, bytes32, uint256, uint256) { + Allocation memory allo = __DEPRECATED_allocations[allocationID]; + return (allo.indexer, allo.subgraphDeploymentID, allo.tokens, allo.accRewardsPerAllocatedToken); + } + /** * @notice Return the current state of an allocation * @dev TODO: Remove after Horizon transition period diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 261dd8805..2fce55365 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.24; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; +import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { DataServicePausable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServicePausable.sol"; @@ -28,6 +29,7 @@ contract SubgraphService is Directory, AllocationManager, SubgraphServiceV1Storage, + IRewardsIssuer, ISubgraphService { using PPMMath for uint256; @@ -177,6 +179,13 @@ contract SubgraphService is return allocations[allocationId]; } + function getAllocationData( + address allocationId + ) external view override returns (address, bytes32, uint256, uint256) { + Allocation.State memory allo = allocations[allocationId]; + return (allo.indexer, allo.subgraphDeploymentId, allo.tokens, allo.accRewardsPerAllocatedToken); + } + function getLegacyAllocation(address allocationId) external view returns (LegacyAllocation.State memory) { return legacyAllocations[allocationId]; } diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index 6d15d2b3c..49c284aaa 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -12,6 +12,8 @@ contract MockRewardsManager is IRewardsManager { function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external {} + function setRewardsIssuer(address _rewardsIssuer, bool _allowed) external {} + // -- Denylist -- function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external {} From 8d788f27eca0b5db872143ba6630e079acaf3a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 22 May 2024 15:17:45 -0300 Subject: [PATCH 041/277] feat: allow presenting 0x00 pois MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/libraries/Allocation.sol | 2 +- .../contracts/utilities/AllocationManager.sol | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index f6e9e0000..f7b5c972a 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -36,7 +36,7 @@ library Allocation { tokens: tokens, createdAt: block.timestamp, closedAt: 0, - lastPOIPresentedAt: block.timestamp, + lastPOIPresentedAt: 0, accRewardsPerAllocatedToken: accRewardsPerAllocatedToken, accRewardsPending: 0 }); diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index f20a5ab90..62a70aee4 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -6,6 +6,7 @@ import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGra import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import { Allocation } from "../libraries/Allocation.sol"; @@ -130,17 +131,16 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // This ensures the rewards are actually skipped and not collected with the next valid POI function _collectIndexingRewards(bytes memory _data) internal returns (uint256) { (address allocationId, bytes32 poi) = abi.decode(_data, (address, bytes32)); - if (poi == bytes32(0)) revert AllocationManagerInvalidZeroPOI(); Allocation.State memory allocation = allocations.get(allocationId); - // Mint indexing rewards, stale POIs get no rewards... - uint256 timeSinceLastPOI = block.number - allocation.lastPOIPresentedAt; - uint256 tokensRewards = timeSinceLastPOI <= maxPOIStaleness + // Mint indexing rewards, 0x00 and stale POIs get no rewards... + uint256 timeSinceLastPOI = block.number - Math.max(allocation.createdAt, allocation.lastPOIPresentedAt); + uint256 tokensRewards = (timeSinceLastPOI <= maxPOIStaleness && poi != bytes32(0)) ? _graphRewardsManager().takeRewards(allocationId) : 0; - // ... but we still take a snapshot to ensure the rewards are not collected with the next valid POI + // ... but we still take a snapshot to ensure the rewards are not accumulated for the next valid POI allocations.snapshotRewards( allocationId, _graphRewardsManager().onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) From 21235909bb9a10f5e401a0d9c08f3c8f2deadc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 22 May 2024 17:45:51 -0300 Subject: [PATCH 042/277] feat: better provision checks, delegation ratio fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 15 ---- .../extensions/DataServiceFees.sol | 2 +- .../extensions/DataServiceFeesStorage.sol | 2 - .../utilities/ProvisionManager.sol | 78 ++++++++++++------- .../utilities/ProvisionManagerStorage.sol | 6 ++ .../staking/HorizonStakingExtension.sol | 5 +- .../contracts/SubgraphService.sol | 19 +++-- .../test/DisputeManager.t.sol | 3 +- 8 files changed, 73 insertions(+), 57 deletions(-) diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index f256cbba7..06c484aa2 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -21,19 +21,4 @@ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1 * @param controller The address of the Graph Horizon controller contract. */ constructor(address controller) GraphDirectory(controller) {} - - /** - * @notice Verifies and accepts the provision of a service provider in the {Graph Horizon staking - * contract}. - * @dev This internal function is a wrapper around {ProvisionManager-checkAndAcceptProvision} - * that ensures the event {ProvisionAccepted} is emitted when called from different contexts. - * - * Emits a {ProvisionAccepted} event. - * - * @param _serviceProvider The address of the service provider. - */ - function _acceptProvision(address _serviceProvider) internal { - _checkAndAcceptProvision(_serviceProvider); - emit ProvisionAccepted(_serviceProvider); - } } diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index b803c9248..2ea9ffe2c 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -66,7 +66,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat uint256 _tokens, uint256 _unlockTimestamp ) internal { - feesProvisionTracker[_feeType].lock(_graphStaking(), _serviceProvider, _tokens, delegationRatio); + feesProvisionTracker[_feeType].lock(_graphStaking(), _serviceProvider, _tokens, maximumDelegationRatio); StakeClaimsList storage claimsList = claimsLists[_feeType][_serviceProvider]; bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index d64f99239..4296a952a 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -15,8 +15,6 @@ abstract contract DataServiceFeesV1Storage { mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => IDataServiceFees.StakeClaimsList list)) public claimsLists; - uint32 public delegationRatio; - /// @dev Gap to allow adding variables in future upgrades uint256[50] private __gap; } diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 946db4b0f..57e14270f 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -13,21 +13,7 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage using ProvisionGetter for IHorizonStaking; using UintRange for uint256; - error ProvisionManagerInvalidProvisionTokens( - uint256 tokens, - uint256 minimumProvisionTokens, - uint256 maximumProvisionTokens - ); - error ProvisionManagerInvalidVerifierCut( - uint256 verifierCut, - uint256 minimumVerifierCut, - uint256 maximumVerifierCut - ); - error ProvisionManagerInvalidThawingPeriod( - uint64 thawingPeriod, - uint64 minimumThawingPeriod, - uint64 maximumThawingPeriod - ); + error ProvisionManagerInvalidValue(bytes message, uint256 value, uint256 min, uint256 max); error ProvisionManagerNotAuthorized(address caller, address serviceProvider, address service); modifier onlyProvisionAuthorized(address serviceProvider) { @@ -41,6 +27,9 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage minimumProvisionTokens = type(uint256).min; maximumProvisionTokens = type(uint256).max; + minimumDelegationRatio = type(uint32).min; + maximumDelegationRatio = type(uint32).max; + minimumThawingPeriod = type(uint64).min; maximumThawingPeriod = type(uint64).max; @@ -48,8 +37,17 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage maximumVerifierCut = type(uint32).max; } - function _checkAndAcceptProvision(address _serviceProvider) internal virtual { - _checkProvisionParameters(_serviceProvider); + /** + * @notice Verifies and accepts the provision of a service provider in the {Graph Horizon staking + * contract}. + * @dev Checks the pending provision parameters, not the current ones. + * + * Emits a {ProvisionAccepted} event. + * + * @param _serviceProvider The address of the service provider. + */ + function _acceptProvisionParameters(address _serviceProvider) internal virtual { + _checkProvisionParameters(_serviceProvider, true); _graphStaking().acceptProvisionParameters(_serviceProvider); } @@ -59,6 +57,11 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage maximumProvisionTokens = _max; } + function _setDelegationRatioRange(uint32 _min, uint32 _max) internal { + minimumDelegationRatio = _min; + maximumDelegationRatio = _max; + } + function _setVerifierCutRange(uint32 _min, uint32 _max) internal { minimumVerifierCut = _min; maximumVerifierCut = _max; @@ -69,25 +72,30 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage maximumThawingPeriod = _max; } - /// @notice Checks if the service provider has a valid provision for the data service in the staking contract - /// @param _serviceProvider The address of the service provider - function _checkProvisionParameters(address _serviceProvider) internal view virtual { + function _checkProvisionTokens(address _serviceProvider) internal view virtual { IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); + _checkValueInRange(provision.tokens, minimumProvisionTokens, maximumProvisionTokens, "tokens"); + } - (uint256 provisionTokensMin, uint256 provisionTokensMax) = _getProvisionTokensRange(); - if (!provision.tokens.isInRange(provisionTokensMin, provisionTokensMax)) { - revert ProvisionManagerInvalidProvisionTokens(provision.tokens, provisionTokensMin, provisionTokensMax); - } + function _checkProvisionDelegationRatio(address _serviceProvider) internal view virtual { + IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); + uint256 delegatedTokens = _graphStaking().getDelegatedTokensAvailable(_serviceProvider, address(this)); + + (uint32 delegationRatioMin, uint32 delegationRatioMax) = _getDelegationRatioRange(); + uint256 delegationRatioToCheck = uint32(delegatedTokens / (provision.tokens - provision.tokensThawing)); + _checkValueInRange(delegationRatioToCheck, delegationRatioMin, delegationRatioMax, "delegationRatio"); + } + + function _checkProvisionParameters(address _serviceProvider, bool _checkPending) internal view virtual { + IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); (uint64 thawingPeriodMin, uint64 thawingPeriodMax) = _getThawingPeriodRange(); - if (!uint256(provision.thawingPeriod).isInRange(thawingPeriodMin, thawingPeriodMax)) { - revert ProvisionManagerInvalidThawingPeriod(provision.thawingPeriod, thawingPeriodMin, thawingPeriodMax); - } + uint64 thawingPeriodToCheck = _checkPending ? provision.thawingPeriodPending : provision.thawingPeriod; + _checkValueInRange(thawingPeriodToCheck, thawingPeriodMin, thawingPeriodMax, "thawingPeriod"); (uint32 verifierCutMin, uint32 verifierCutMax) = _getVerifierCutRange(); - if (!uint256(provision.maxVerifierCut).isInRange(verifierCutMin, verifierCutMax)) { - revert ProvisionManagerInvalidVerifierCut(provision.maxVerifierCut, verifierCutMin, verifierCutMax); - } + uint32 maxVerifierCutToCheck = _checkPending ? provision.maxVerifierCutPending : provision.maxVerifierCut; + _checkValueInRange(maxVerifierCutToCheck, verifierCutMin, verifierCutMax, "maxVerifierCut"); } // -- Provision Parameters: getters -- @@ -95,6 +103,10 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage return (minimumProvisionTokens, maximumProvisionTokens); } + function _getDelegationRatioRange() internal view virtual returns (uint32 min, uint32 max) { + return (minimumDelegationRatio, maximumDelegationRatio); + } + function _getThawingPeriodRange() internal view virtual returns (uint64 min, uint64 max) { return (minimumThawingPeriod, maximumThawingPeriod); } @@ -106,4 +118,10 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage function _getProvision(address _serviceProvider) internal view returns (IHorizonStaking.Provision memory) { return _graphStaking().get(_serviceProvider); } + + function _checkValueInRange(uint256 _value, uint256 _min, uint256 _max, bytes memory _revertMessage) private pure { + if (!_value.isInRange(_min, _max)) { + revert ProvisionManagerInvalidValue(_revertMessage, _value, _min, _max); + } + } } diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index e7a25e6ab..2f129adef 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -8,6 +8,12 @@ abstract contract ProvisionManagerV1Storage { /// @notice The maximum amount of tokens allowed to register a provision in the data service uint256 public maximumProvisionTokens; + /// @notice Minimum delegation to self stake ratio required + uint32 public minimumDelegationRatio; + + /// @notice Maximum delegation to self stake ratio allowed for a service provider + uint32 public maximumDelegationRatio; + /// @notice The minimum thawing period required to register a provision in the data service uint64 public minimumThawingPeriod; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 469e4cf3f..7142fbd31 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -122,12 +122,13 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas uint32 delegationRatio ) external view override returns (uint256) { uint256 providerTokens = _provisions[serviceProvider][verifier].tokens; - uint256 tokensDelegatedMax = providerTokens * (uint256(delegationRatio)); + uint256 providerThawingTokens = _provisions[serviceProvider][verifier].tokensThawing; + uint256 tokensDelegatedMax = (providerTokens - providerThawingTokens) * (uint256(delegationRatio)); uint256 tokensDelegatedCapacity = MathUtils.min( getDelegatedTokensAvailable(serviceProvider, verifier), tokensDelegatedMax ); - return providerTokens - _provisions[serviceProvider][verifier].tokensThawing + tokensDelegatedCapacity; + return providerTokens - providerThawingTokens + tokensDelegatedCapacity; } function getServiceProvider(address serviceProvider) external view override returns (ServiceProvider memory) { diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 2fce55365..3836b7e57 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -60,7 +60,8 @@ contract SubgraphService is address disputeManager, address tapVerifier, address curation, - uint256 minimumProvisionTokens + uint256 minimumProvisionTokens, + uint32 maximumDelegationRatio ) Ownable(msg.sender) DataService(graphController) @@ -68,6 +69,7 @@ contract SubgraphService is AllocationManager("SubgraphService", "1.0") { _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); + _setDelegationRatioRange(type(uint32).min, maximumDelegationRatio); } function register( @@ -97,8 +99,8 @@ contract SubgraphService is } // Ensure the service provider created a valid provision for the data service - // and accept it in the staking contract - _acceptProvision(indexer); + _checkProvisionParameters(indexer, false); + _checkProvisionTokens(indexer); emit ServiceProviderRegistered(indexer); } @@ -107,18 +109,21 @@ contract SubgraphService is address indexer, bytes calldata ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { - _acceptProvision(indexer); + _checkProvisionTokens(indexer); + _acceptProvisionParameters(indexer); + emit ProvisionAccepted(indexer); } function startService( address indexer, bytes calldata data ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + _checkProvisionTokens(indexer); (bytes32 subgraphDeploymentId, uint256 tokens, address allocationId, bytes memory allocationProof) = abi.decode( data, (bytes32, uint256, address, bytes) ); - _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof, delegationRatio); + _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof, maximumDelegationRatio); emit ServiceStarted(indexer); } @@ -136,7 +141,8 @@ contract SubgraphService is address allocationId, uint256 tokens ) external onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { - _resizeAllocation(allocationId, tokens, delegationRatio); + _checkProvisionTokens(indexer); + _resizeAllocation(allocationId, tokens, maximumDelegationRatio); } function collect( @@ -144,6 +150,7 @@ contract SubgraphService is IGraphPayments.PaymentTypes paymentType, bytes calldata data ) external override onlyRegisteredIndexer(indexer) whenNotPaused { + _checkProvisionTokens(indexer); uint256 paymentCollected = 0; if (paymentType == IGraphPayments.PaymentTypes.QueryFee) { diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol index bc8e8f42d..8d338299f 100644 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -89,7 +89,8 @@ contract DisputeManagerTest is Test { address(disputeManager), tapVerifier, curation, - 1000 ether + 1000 ether, + 16 ); disputeManager.setSubgraphService(address(subgraphService)); From f657198bfefd8f2b00d04679375e7b0bcf00a7cc Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 21 May 2024 18:47:05 -0300 Subject: [PATCH 043/277] chore: fix unit tests and refactor --- .../contracts/data-service/GraphDirectory.sol | 1 + .../contracts/payments/GraphPayments.sol | 6 +- packages/horizon/test/GraphBase.t.sol | 36 +++++----- .../horizon/test/escrow/GraphEscrow.t.sol | 30 +++++--- packages/horizon/test/escrow/collect.t.sol | 69 ++++++++----------- packages/horizon/test/escrow/collector.t.sol | 27 ++------ packages/horizon/test/escrow/deposit.t.sol | 2 +- packages/horizon/test/escrow/thaw.t.sol | 6 +- packages/horizon/test/escrow/withdraw.t.sol | 2 +- .../horizon/test/payments/GraphPayments.t.sol | 20 +++--- .../horizon-staking/HorizonStaking.t.sol | 26 ++++++- packages/horizon/test/utils/Constants.sol | 4 +- 12 files changed, 120 insertions(+), 109 deletions(-) diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index f05d9db66..805136db1 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -16,6 +16,7 @@ import { IGraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/IG import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; +import "forge-std/console.sol"; /** * @title GraphDirectory contract * @notice This contract is meant to be inherited by other contracts that diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 2ba8f8dc8..8fddc6a07 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -69,7 +69,11 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora } // Pay the rest to the receiver - uint256 tokensReceiverRemaining = tokens - tokensProtocol - tokensDataService - tokensDelegationPool; + uint256 totalCut = tokensProtocol + tokensDataService + tokensDelegationPool; + if (totalCut > tokens) { + revert GraphPaymentsCollectorInsufficientAmount(tokens, totalCut); + } + uint256 tokensReceiverRemaining = tokens - totalCut; _graphToken().pushTokens(receiver, tokensReceiverRemaining); emit GraphPaymentsCollected( diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 36721ed2c..51a5b4d5a 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -67,10 +67,13 @@ abstract contract GraphBaseTest is Test, Constants { } function deployProtocolContracts() private { - vm.prank(users.governor); + vm.startPrank(users.governor); controller = new Controller(); + controller.setContractProxy(keccak256("GraphToken"), address(token)); + vm.stopPrank(); + - // GraphPayments preddict address + // GraphPayments predict address bytes32 saltPayments = keccak256("GraphPaymentsSalt"); bytes32 paymentsHash = keccak256(bytes.concat( vm.getCode("GraphPayments.sol:GraphPayments"), @@ -82,7 +85,7 @@ abstract contract GraphBaseTest is Test, Constants { users.deployer ); - // GraphEscrow preddict address + // GraphEscrow predict address bytes32 saltEscrow = keccak256("GraphEscrowSalt"); bytes32 escrowHash = keccak256(bytes.concat( vm.getCode("GraphEscrow.sol:GraphEscrow"), @@ -98,7 +101,7 @@ abstract contract GraphBaseTest is Test, Constants { users.deployer ); - // HorizonStakingExtension preddict address + // HorizonStakingExtension predict address bytes32 saltHorizonStakingExtension = keccak256("HorizonStakingExtensionSalt"); bytes32 horizonStakingExtensionHash = keccak256(bytes.concat( vm.getCode("HorizonStakingExtension.sol:HorizonStakingExtension"), @@ -110,7 +113,7 @@ abstract contract GraphBaseTest is Test, Constants { users.deployer ); - // HorizonStaking preddict address + // HorizonStaking predict address bytes32 saltHorizonStaking = keccak256("saltHorizonStaking"); bytes32 horizonStakingHash = keccak256(bytes.concat( vm.getCode("HorizonStaking.sol:HorizonStaking"), @@ -120,18 +123,17 @@ abstract contract GraphBaseTest is Test, Constants { subgraphDataServiceAddress ) )); - // address predictedAddressHorizonStaking = vm.computeCreate2Address( - // saltHorizonStaking, - // horizonStakingHash, - // users.deployer - // ); + address predictedAddressHorizonStaking = vm.computeCreate2Address( + saltHorizonStaking, + horizonStakingHash, + users.deployer + ); // Setup controller vm.startPrank(users.governor); - controller.setContractProxy(keccak256("GraphToken"), address(token)); controller.setContractProxy(keccak256("GraphEscrow"), predictedAddressEscrow); controller.setContractProxy(keccak256("GraphPayments"), predictedPaymentsAddress); - // controller.setContractProxy(keccak256("Staking"), predictedAddressHorizonStaking); + controller.setContractProxy(keccak256("Staking"), address(predictedAddressHorizonStaking)); vm.stopPrank(); vm.startPrank(users.deployer); @@ -144,16 +146,16 @@ abstract contract GraphBaseTest is Test, Constants { revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod ); + stakingExtension = new HorizonStakingExtension{salt: saltHorizonStakingExtension}( + address(controller), + subgraphDataServiceAddress + ); stakingBase = new HorizonStaking{salt: saltHorizonStaking}( address(controller), - predictedAddressHorizonStakingExtension, + address(stakingExtension), subgraphDataServiceAddress ); staking = IHorizonStaking(address(stakingBase)); - // stakingExtension = new HorizonStakingExtension{salt: saltHorizonStakingExtension}( - // address(controller), - // subgraphDataServiceAddress - // ); vm.stopPrank(); } diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index f420c1964..fffa82830 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -13,15 +13,23 @@ contract GraphEscrowTest is HorizonStakingSharedTest { vm.stopPrank(); } - modifier approveEscrow(uint256 amount) { - _approveEscrow(amount); + modifier approveEscrow(uint256 tokens) { + changePrank(users.gateway); + _approveEscrow(tokens); _; } - modifier depositTokens(uint256 amount) { - vm.assume(amount > 0); - vm.assume(amount <= 10000 ether); - _depositTokens(amount); + modifier useDeposit(uint256 tokens) { + changePrank(users.gateway); + vm.assume(tokens > 0); + vm.assume(tokens <= 10_000_000_000 ether); + _depositTokens(tokens); + _; + } + + modifier useCollector(uint256 tokens) { + changePrank(users.gateway); + escrow.approveCollector(users.verifier, tokens); _; } @@ -29,12 +37,12 @@ contract GraphEscrowTest is HorizonStakingSharedTest { HorizonStakingSharedTest.setUp(); } - function _depositTokens(uint256 amount) internal { - token.approve(address(escrow), amount); - escrow.deposit(users.indexer, amount); + function _depositTokens(uint256 tokens) internal { + token.approve(address(escrow), tokens); + escrow.deposit(users.indexer, tokens); } - function _approveEscrow(uint256 amount) internal { - token.approve(address(escrow), amount); + function _approveEscrow(uint256 tokens) internal { + token.approve(address(escrow), tokens); } } \ No newline at end of file diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 1f2b733f6..db7f549e8 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -8,68 +8,57 @@ import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; contract GraphEscrowCollectTest is GraphEscrowTest { - function testCollect() public { - uint256 amount = 1000 ether; - createProvision(amount); - setDelegationFeeCut(0, 100000); - + function testCollect_Tokens(uint256 amount, uint256 tokensDataService) public useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { + uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; + uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; + vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); + vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 1000 ether); + escrow.approveCollector(users.verifier, amount); + _depositTokens(amount); vm.stopPrank(); uint256 indexerPreviousBalance = token.balanceOf(users.indexer); vm.prank(users.verifier); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, 100 ether, subgraphDataServiceAddress, 3 ether); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); uint256 indexerBalance = token.balanceOf(users.indexer); - assertEq(indexerBalance - indexerPreviousBalance, 86 ether); + uint256 indexerExpectedPayment = amount - tokensDataService - tokensProtocol - tokensDelegatoion; + assertEq(indexerBalance - indexerPreviousBalance, indexerExpectedPayment); + assertTrue(true); } - function testCollect_RevertWhen_CollectorNotAuthorized() public { - address indexer = address(0xA3); - uint256 amount = 1000 ether; - + function testCollect_RevertWhen_CollectorNotAuthorized(uint256 amount) public { vm.startPrank(users.verifier); uint256 dataServiceCut = 30000; // 3% bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); vm.expectRevert(expectedError); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, indexer, amount, subgraphDataServiceAddress, dataServiceCut); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, dataServiceCut); vm.stopPrank(); } - function testCollect_RevertWhen_CollectorHasInsufficientAmount() public { - vm.prank(users.gateway); - escrow.approveCollector(users.verifier, 100 ether); - - address indexer = address(0xA3); - uint256 amount = 1000 ether; - - vm.startPrank(users.gateway); - token.approve(address(escrow), amount); - escrow.deposit(indexer, amount); - vm.stopPrank(); + function testCollect_RevertWhen_CollectorHasInsufficientAmount( + uint256 amount, + uint256 insufficientAmount + ) public useGateway useCollector(insufficientAmount) useDeposit(amount) { + vm.assume(insufficientAmount < amount); - vm.startPrank(users.verifier); - uint256 dataServiceCut = 30 ether; - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", 100 ether, 1000 ether); + changePrank(users.verifier); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", insufficientAmount, amount); vm.expectRevert(expectedError); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, indexer, 1000 ether, subgraphDataServiceAddress, dataServiceCut); - vm.stopPrank(); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); } - function testCollect_RevertWhen_SenderHasInsufficientAmountInEscrow() public { - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - token.approve(address(escrow), 1000 ether); - escrow.deposit(users.indexer, 100 ether); - vm.stopPrank(); + function testCollect_RevertWhen_SenderHasInsufficientAmountInEscrow( + uint256 amount, + uint256 insufficientAmount + ) public useGateway useCollector(amount) useDeposit(insufficientAmount) { + vm.assume(insufficientAmount < amount); - vm.prank(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", 100 ether, 200 ether); + changePrank(users.verifier); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", insufficientAmount, amount); vm.expectRevert(expectedError); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, 200 ether, subgraphDataServiceAddress, 3 ether); + escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); vm.stopPrank(); } } \ No newline at end of file diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index f4ef2b11c..be1524056 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -6,15 +6,10 @@ import "forge-std/Test.sol"; import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowCollectorTest is GraphEscrowTest { - function setUp() public virtual override { - GraphEscrowTest.setUp(); - vm.prank(users.gateway); - escrow.approveCollector(users.verifier, 1000 ether); - } // Collector approve tests - function testCollector_Approve() public view { + function testCollector_Approve(uint256 amount) public useGateway useCollector(amount) { (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); assertEq(authorized, true); assertEq(thawEndTimestamp, 0); @@ -22,8 +17,7 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { // Collector thaw tests - function testCollector_Thaw() public { - vm.prank(users.gateway); + function testCollector_Thaw(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); @@ -33,15 +27,13 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { // Collector cancel thaw tests - function testCollector_CancelThaw() public { - vm.prank(users.gateway); + function testCollector_CancelThaw(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); assertEq(authorized, true); assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); - vm.prank(users.gateway); escrow.cancelThawCollector(users.verifier); (authorized,, thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); @@ -49,7 +41,7 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { assertEq(thawEndTimestamp, 0); } - function testCollector_RevertWhen_CancelThawIsNotThawing() public { + function testCollector_RevertWhen_CancelThawIsNotThawing(uint256 amount) public useGateway useCollector(amount) { bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); vm.expectRevert(expectedError); escrow.cancelThawCollector(users.verifier); @@ -58,30 +50,25 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { // Collector revoke tests - function testCollector_Revoke() public { - vm.startPrank(users.gateway); + function testCollector_Revoke(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); skip(revokeCollectorThawingPeriod + 1); escrow.revokeCollector(users.verifier); - vm.stopPrank(); (bool authorized,,) = escrow.authorizedCollectors(users.gateway, users.verifier); assertEq(authorized, false); } - function testCollector_RevertWhen_RevokeIsNotThawing() public { + function testCollector_RevertWhen_RevokeIsNotThawing(uint256 amount) public useGateway useCollector(amount) { bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); vm.expectRevert(expectedError); - vm.prank(users.gateway); escrow.revokeCollector(users.verifier); } - function testCollector_RevertWhen_RevokeIsStillThawing() public { - vm.startPrank(users.gateway); + function testCollector_RevertWhen_RevokeIsStillThawing(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); vm.expectRevert(expectedError); escrow.revokeCollector(users.verifier); - vm.stopPrank(); } } \ No newline at end of file diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol index 48574880e..8a83043e2 100644 --- a/packages/horizon/test/escrow/deposit.t.sol +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -7,7 +7,7 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowDepositTest is GraphEscrowTest { - function testDeposit_Tokens(uint256 amount) public useGateway depositTokens(amount) { + function testDeposit_Tokens(uint256 amount) public useGateway useDeposit(amount) { (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); assertEq(indexerEscrowBalance, amount); } diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 51400feac..a9d95460b 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -7,7 +7,7 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowThawTest is GraphEscrowTest { - function testThaw_Tokens(uint256 amount) public useGateway depositTokens(amount) { + function testThaw_Tokens(uint256 amount) public useGateway useDeposit(amount) { escrow.thaw(users.indexer, amount); (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.indexer); @@ -17,7 +17,7 @@ contract GraphEscrowThawTest is GraphEscrowTest { function testThaw_RevertWhen_InsufficientThawAmount( uint256 amount - ) public useGateway depositTokens(amount) { + ) public useGateway useDeposit(amount) { bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientThawAmount()"); vm.expectRevert(expectedError); escrow.thaw(users.indexer, 0); @@ -25,7 +25,7 @@ contract GraphEscrowThawTest is GraphEscrowTest { function testThaw_RevertWhen_InsufficientAmount( uint256 amount - ) public useGateway depositTokens(amount) { + ) public useGateway useDeposit(amount) { uint256 overAmount = amount + 1; bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", amount, overAmount); vm.expectRevert(expectedError); diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index 075a16a74..be47fea83 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -29,7 +29,7 @@ contract GraphEscrowWithdrawTest is GraphEscrowTest { assertEq(indexerEscrowBalance, amount - thawAmount); } - function testWithdraw_RevertWhen_NotThawing(uint256 amount) public useGateway depositTokens(amount) { + function testWithdraw_RevertWhen_NotThawing(uint256 amount) public useGateway useDeposit(amount) { bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); vm.expectRevert(expectedError); escrow.withdraw(users.indexer); diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 4bf00ff8d..74f255d9c 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -9,12 +9,10 @@ import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaki contract GraphPaymentsTest is HorizonStakingSharedTest { - function testCollect() public { - // Setup Staking - uint256 amount = 1000 ether; - createProvision(amount); - setDelegationFeeCut(0, 100000); - + function testCollect(uint256 amount, uint256 tokensDataService) public useProvision(amount, 0, 0) useDelegationFeeCut(0, 100000) { + uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; + uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; + vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); address escrowAddress = address(escrow); // Add tokens in escrow @@ -23,18 +21,18 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { approve(address(payments), amount); // Collect payments through GraphPayments - uint256 dataServiceCut = 30 ether; // 3% uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - payments.collect(IGraphPayments.PaymentTypes.IndexingFee, users.indexer, amount, subgraphDataServiceAddress, dataServiceCut); + payments.collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); vm.stopPrank(); uint256 indexerBalance = token.balanceOf(users.indexer); - assertEq(indexerBalance - indexerPreviousBalance, 860 ether); + uint256 expectedPayment = amount - tokensDataService - tokensProtocol - tokensDelegatoion; + assertEq(indexerBalance - indexerPreviousBalance, expectedPayment); uint256 dataServiceBalance = token.balanceOf(subgraphDataServiceAddress); - assertEq(dataServiceBalance, 30 ether); + assertEq(dataServiceBalance, tokensDataService); uint256 delegatorBalance = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(delegatorBalance, 100 ether); + assertEq(delegatorBalance, tokensDelegatoion); } } diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol index c5aec8aa2..c65032e9a 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol @@ -7,6 +7,18 @@ import { GraphBaseTest } from "../../GraphBase.t.sol"; abstract contract HorizonStakingSharedTest is GraphBaseTest { + modifier useProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) { + vm.assume(tokens <= 10_000_000_000 ether); + vm.assume(tokens > 1e18); + _createProvision(tokens, maxVerifierCut, thawingPeriod); + _; + } + + modifier useDelegationFeeCut(uint256 paymentType, uint256 cut) { + _setDelegationFeeCut(paymentType, cut); + _; + } + /* Set Up */ function setUp() public virtual override { @@ -15,14 +27,22 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { /* Helpers */ - function createProvision(uint256 tokens) internal { + function _createProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) internal { vm.startPrank(users.indexer); token.approve(address(staking), tokens); staking.stakeTo(users.indexer, tokens); - staking.provision(users.indexer, subgraphDataServiceAddress, tokens, 0, 0); + staking.provision( + users.indexer, + subgraphDataServiceAddress, + tokens, + maxVerifierCut, + thawingPeriod + ); + vm.stopPrank(); } - function setDelegationFeeCut(uint256 paymentType, uint256 cut) internal { + function _setDelegationFeeCut(uint256 paymentType, uint256 cut) internal { + vm.prank(users.indexer); staking.setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, cut); } } diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index 8e03271ec..ff7f77dfb 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -2,9 +2,11 @@ pragma solidity ^0.8.24; abstract contract Constants { + uint256 internal constant MAX_PPM = 1000000; // 100% in parts per million + uint256 internal constant delegationFeeCut = 100000; // 10% in parts per million // GraphEscrow parameters uint256 internal constant withdrawEscrowThawingPeriod = 60; - // GraphPayments parameters uint256 internal constant revokeCollectorThawingPeriod = 60; + // GraphPayments parameters uint256 internal constant protocolPaymentCut = 10000; } \ No newline at end of file From 31ae8e451d1890dd93e2a3ef1ceb4acb530d128f Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 21 May 2024 18:54:18 -0300 Subject: [PATCH 044/277] fix: approving collector for smaller allowance --- packages/horizon/contracts/payments/PaymentsEscrow.sol | 9 +++++++-- packages/horizon/test/escrow/collector.t.sol | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index f8ac5ca37..345b4309d 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -84,8 +84,13 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // approve a data service to collect funds function approveCollector(address dataService, uint256 amount) external { - authorizedCollectors[msg.sender][dataService].authorized = true; - authorizedCollectors[msg.sender][dataService].amount = amount; + IGraphEscrow.Collector storage collector = authorizedCollectors[msg.sender][dataService]; + if (collector.amount > amount) { + revert GraphEscrowCollectorInsufficientAmount(collector.amount, amount); + } + + collector.authorized = true; + collector.amount = amount; emit AuthorizedCollector(msg.sender, dataService); } diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index be1524056..c87545b1a 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -15,6 +15,16 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { assertEq(thawEndTimestamp, 0); } + function testCollector_RevertWhen_ApprovingForSmallerAllowance( + uint256 amount, + uint256 smallerAmount + ) public useGateway useCollector(amount) { + vm.assume(smallerAmount < amount); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", amount, smallerAmount); + vm.expectRevert(expectedError); + escrow.approveCollector(users.verifier, smallerAmount); + } + // Collector thaw tests function testCollector_Thaw(uint256 amount) public useGateway useCollector(amount) { From 0c438c842ba2b3b30569fb2c9c32e4f5d9453901 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 22 May 2024 11:59:33 -0300 Subject: [PATCH 045/277] fix: type error --- packages/horizon/contracts/payments/PaymentsEscrow.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 345b4309d..f1c684887 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -84,7 +84,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // approve a data service to collect funds function approveCollector(address dataService, uint256 amount) external { - IGraphEscrow.Collector storage collector = authorizedCollectors[msg.sender][dataService]; + Collector storage collector = authorizedCollectors[msg.sender][dataService]; if (collector.amount > amount) { revert GraphEscrowCollectorInsufficientAmount(collector.amount, amount); } From 5247ebf93ecf04fc276e091f6c0f7175cce0d04f Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 22 May 2024 18:26:54 -0300 Subject: [PATCH 046/277] fix: rebase and fixes --- .../contracts/upgrades/GraphProxy.sol | 5 +- .../contracts/upgrades/GraphProxyAdmin.sol | 2 +- .../contracts/upgrades/GraphProxyStorage.sol | 2 +- .../contracts/payments/PaymentsEscrow.sol | 4 +- packages/horizon/test/GraphBase.t.sol | 57 ++++++++----------- packages/horizon/test/HorizonStaking.t.sol | 33 ----------- packages/horizon/test/HorizonStaking.ts | 38 ------------- 7 files changed, 28 insertions(+), 113 deletions(-) delete mode 100644 packages/horizon/test/HorizonStaking.t.sol delete mode 100644 packages/horizon/test/HorizonStaking.ts diff --git a/packages/contracts/contracts/upgrades/GraphProxy.sol b/packages/contracts/contracts/upgrades/GraphProxy.sol index 7d227b065..c5c01ca8f 100644 --- a/packages/contracts/contracts/upgrades/GraphProxy.sol +++ b/packages/contracts/contracts/upgrades/GraphProxy.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; - -import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +pragma solidity >=0.6.12 <0.9.0; import { GraphProxyStorage } from "./GraphProxyStorage.sol"; @@ -160,7 +158,6 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy { */ function _acceptUpgrade() internal { address _pendingImplementation = _getPendingImplementation(); - require(Address.isContract(_pendingImplementation), "Impl must be a contract"); require(_pendingImplementation != address(0), "Impl cannot be zero address"); require(msg.sender == _pendingImplementation, "Only pending implementation"); diff --git a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol index 7d809d5ec..8fb735901 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; import { Governed } from "../governance/Governed.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol index 05b922647..42e2a0545 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity >=0.6.12 <0.9.0; /** * @title Graph Proxy Storage diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index f1c684887..9404190be 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -78,8 +78,8 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { revert GraphEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD); } - revokeCollectorThawingPeriod = revokeCollectorThawingPeriod; - withdrawEscrowThawingPeriod = withdrawEscrowThawingPeriod; + REVOKE_COLLECTOR_THAWING_PERIOD = revokeCollectorThawingPeriod; + WITHDRAW_ESCROW_THAWING_PERIOD = withdrawEscrowThawingPeriod; } // approve a data service to collect funds diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 51a5b4d5a..f348ca3f0 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -3,6 +3,8 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; +import { GraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/GraphProxyAdmin.sol"; +import { GraphProxy } from "@graphprotocol/contracts/contracts/upgrades/GraphProxy.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; import { PaymentsEscrow } from "contracts/payments/PaymentsEscrow.sol"; @@ -18,6 +20,7 @@ abstract contract GraphBaseTest is Test, Constants { /* Contracts */ + GraphProxyAdmin public proxyAdmin; Controller public controller; MockGRTToken public token; GraphPayments public payments; @@ -41,6 +44,7 @@ abstract contract GraphBaseTest is Test, Constants { function setUp() public virtual { // Deploy ERC20 token + vm.prank(users.deployer); token = new MockGRTToken(); // Setup Users @@ -68,10 +72,13 @@ abstract contract GraphBaseTest is Test, Constants { function deployProtocolContracts() private { vm.startPrank(users.governor); + proxyAdmin = new GraphProxyAdmin(); controller = new Controller(); - controller.setContractProxy(keccak256("GraphToken"), address(token)); vm.stopPrank(); + // Staking Proxy + vm.prank(users.deployer); + GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); // GraphPayments predict address bytes32 saltPayments = keccak256("GraphPaymentsSalt"); @@ -101,39 +108,16 @@ abstract contract GraphBaseTest is Test, Constants { users.deployer ); - // HorizonStakingExtension predict address - bytes32 saltHorizonStakingExtension = keccak256("HorizonStakingExtensionSalt"); - bytes32 horizonStakingExtensionHash = keccak256(bytes.concat( - vm.getCode("HorizonStakingExtension.sol:HorizonStakingExtension"), - abi.encode(address(controller), subgraphDataServiceAddress) - )); - address predictedAddressHorizonStakingExtension = vm.computeCreate2Address( - saltHorizonStakingExtension, - horizonStakingExtensionHash, - users.deployer - ); - - // HorizonStaking predict address - bytes32 saltHorizonStaking = keccak256("saltHorizonStaking"); - bytes32 horizonStakingHash = keccak256(bytes.concat( - vm.getCode("HorizonStaking.sol:HorizonStaking"), - abi.encode( - address(controller), - predictedAddressHorizonStakingExtension, - subgraphDataServiceAddress - ) - )); - address predictedAddressHorizonStaking = vm.computeCreate2Address( - saltHorizonStaking, - horizonStakingHash, - users.deployer - ); - // Setup controller vm.startPrank(users.governor); - controller.setContractProxy(keccak256("GraphEscrow"), predictedAddressEscrow); + controller.setContractProxy(keccak256("GraphToken"), address(token)); + controller.setContractProxy(keccak256("PaymentsEscrow"), predictedAddressEscrow); controller.setContractProxy(keccak256("GraphPayments"), predictedPaymentsAddress); - controller.setContractProxy(keccak256("Staking"), address(predictedAddressHorizonStaking)); + controller.setContractProxy(keccak256("Staking"), address(stakingProxy)); + controller.setContractProxy(keccak256("EpochManager"), makeAddr("EpochManager")); + controller.setContractProxy(keccak256("RewardsManager"), makeAddr("RewardsManager")); + controller.setContractProxy(keccak256("Curation"), makeAddr("Curation")); + controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); vm.stopPrank(); vm.startPrank(users.deployer); @@ -146,16 +130,21 @@ abstract contract GraphBaseTest is Test, Constants { revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod ); - stakingExtension = new HorizonStakingExtension{salt: saltHorizonStakingExtension}( + stakingExtension = new HorizonStakingExtension( address(controller), subgraphDataServiceAddress ); - stakingBase = new HorizonStaking{salt: saltHorizonStaking}( + stakingBase = new HorizonStaking( address(controller), address(stakingExtension), subgraphDataServiceAddress ); - staking = IHorizonStaking(address(stakingBase)); + vm.stopPrank(); + + vm.startPrank(users.governor); + proxyAdmin.upgrade(stakingProxy, address(stakingBase)); + proxyAdmin.acceptProxy(stakingBase, stakingProxy); + staking = IHorizonStaking(address(stakingProxy)); vm.stopPrank(); } diff --git a/packages/horizon/test/HorizonStaking.t.sol b/packages/horizon/test/HorizonStaking.t.sol deleted file mode 100644 index 55088f0fe..000000000 --- a/packages/horizon/test/HorizonStaking.t.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.24; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import { HorizonStaking } from "../contracts/staking/HorizonStaking.sol"; -import { ControllerMock } from "../contracts/mocks/ControllerMock.sol"; -import { HorizonStakingExtension } from "../contracts/staking/HorizonStakingExtension.sol"; -import { ExponentialRebates } from "../contracts/staking/libraries/ExponentialRebates.sol"; -import { IHorizonStaking } from "../contracts/interfaces/IHorizonStaking.sol"; - -contract HorizonStakingTest is Test { - HorizonStakingExtension ext; - IHorizonStaking staking; - ControllerMock controller; - - function setUp() public { - console.log("Deploying Controller mock"); - controller = new ControllerMock(address(0x1)); - console.log("Deploying HorizonStaking"); - ext = new HorizonStakingExtension(address(controller), address(0x1)); - staking = IHorizonStaking(address(new HorizonStaking(address(controller), address(ext), address(0x1)))); - } - - function test_SetGlobalOperator() public { - address operator = address(0x1337); - address dataService = address(0x1338); - address serviceProvider = address(this); - - staking.setOperator(operator, dataService, true); - assertTrue(staking.isAuthorized(operator, serviceProvider, dataService)); - } -} diff --git a/packages/horizon/test/HorizonStaking.ts b/packages/horizon/test/HorizonStaking.ts deleted file mode 100644 index 28eb281f7..000000000 --- a/packages/horizon/test/HorizonStaking.ts +++ /dev/null @@ -1,38 +0,0 @@ -import hardhat from 'hardhat' - -import { expect } from 'chai' -import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { ZeroAddress } from 'ethers' -import { IHorizonStaking } from '../typechain-types' - -const ethers = hardhat.ethers - -describe('HorizonStaking', function () { - async function deployFixture() { - const [owner] = await ethers.getSigners() - const ControllerMock = await ethers.getContractFactory('ControllerMock') - const controller = await ControllerMock.deploy(owner.address) - await controller.waitForDeployment() - const ExponentialRebates = await ethers.getContractFactory('ExponentialRebates') - const exponentialRebates = await ExponentialRebates.deploy() - await exponentialRebates.waitForDeployment() - const HorizonStakingExtension = await ethers.getContractFactory('HorizonStakingExtension', { libraries: { ExponentialRebates: exponentialRebates.target } }) - const horizonStakingExtension = await HorizonStakingExtension.deploy(controller.target, ZeroAddress) - await horizonStakingExtension.waitForDeployment() - const HorizonStaking = await ethers.getContractFactory('HorizonStaking') - const horizonStakingContract = await HorizonStaking.deploy(controller.target, horizonStakingExtension.target, ZeroAddress) - await horizonStakingContract.waitForDeployment() - const horizonStaking = (await ethers.getContractAt('IHorizonStaking', horizonStakingContract.target)) as unknown as IHorizonStaking - return { horizonStaking, owner } - } - - describe('setOperator', function () { - it('adds an operator', async function () { - const { horizonStaking, owner } = await loadFixture(deployFixture) - const verifier = ethers.Wallet.createRandom().address - const operator = ethers.Wallet.createRandom().address - await horizonStaking.connect(owner).setOperator(operator, verifier, true) - expect(await horizonStaking.isAuthorized(operator, owner, verifier)).to.be.true - }) - }) -}) From 8947c0780f8c11d800986a4e45095c1745db597e Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 22 May 2024 18:39:34 -0300 Subject: [PATCH 047/277] fix: more rebase fixes --- packages/horizon/test/GraphBase.t.sol | 2 ++ packages/horizon/test/escrow/collect.t.sol | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index f348ca3f0..3055c9245 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -118,6 +118,8 @@ abstract contract GraphBaseTest is Test, Constants { controller.setContractProxy(keccak256("RewardsManager"), makeAddr("RewardsManager")); controller.setContractProxy(keccak256("Curation"), makeAddr("Curation")); controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); + controller.setContractProxy(keccak256("BridgeEscrow"), makeAddr("BridgeEscrow")); + controller.setContractProxy(keccak256("GraphProxyAdmin"), makeAddr("GraphProxyAdmin")); vm.stopPrank(); vm.startPrank(users.deployer); diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index db7f549e8..4c66cfc0c 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -20,7 +20,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { uint256 indexerPreviousBalance = token.balanceOf(users.indexer); vm.prank(users.verifier); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); + escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); uint256 indexerBalance = token.balanceOf(users.indexer); uint256 indexerExpectedPayment = amount - tokensDataService - tokensProtocol - tokensDelegatoion; @@ -33,7 +33,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { uint256 dataServiceCut = 30000; // 3% bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); vm.expectRevert(expectedError); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, dataServiceCut); + escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, dataServiceCut); vm.stopPrank(); } @@ -46,7 +46,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { changePrank(users.verifier); bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", insufficientAmount, amount); vm.expectRevert(expectedError); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); + escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); } function testCollect_RevertWhen_SenderHasInsufficientAmountInEscrow( @@ -58,7 +58,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { changePrank(users.verifier); bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", insufficientAmount, amount); vm.expectRevert(expectedError); - escrow.collect(IGraphPayments.PaymentTypes.IndexingFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); + escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); vm.stopPrank(); } } \ No newline at end of file From abbadf67ba29e2eb24fd0cd5adb01d8cb718a240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 11:06:24 -0300 Subject: [PATCH 048/277] feat: add onlyValidProvision modifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../utilities/ProvisionManager.sol | 7 ++++ .../contracts/SubgraphService.sol | 37 +++++++++++++------ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 57e14270f..54a24b9bc 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -23,6 +23,13 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage _; } + modifier onlyValidProvision(address serviceProvider) virtual { + _checkProvisionTokens(serviceProvider); + _checkProvisionDelegationRatio(serviceProvider); + _checkProvisionParameters(serviceProvider, false); + _; + } + constructor() { minimumProvisionTokens = type(uint256).min; maximumProvisionTokens = type(uint256).max; diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 3836b7e57..2f8a504fb 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -55,6 +55,15 @@ contract SubgraphService is _; } + /** + * @dev Strict delegation ratio not enforced. + */ + modifier onlyValidProvision(address indexer) override { + _checkProvisionTokens(indexer); + _checkProvisionParameters(indexer, false); + _; + } + constructor( address graphController, address disputeManager, @@ -75,7 +84,7 @@ contract SubgraphService is function register( address indexer, bytes calldata data - ) external override onlyProvisionAuthorized(indexer) whenNotPaused { + ) external override onlyProvisionAuthorized(indexer) onlyValidProvision(indexer) whenNotPaused { (string memory url, string memory geohash, address rewardsDestination) = abi.decode( data, (string, string, address) @@ -98,10 +107,6 @@ contract SubgraphService is _setRewardsDestination(indexer, rewardsDestination); } - // Ensure the service provider created a valid provision for the data service - _checkProvisionParameters(indexer, false); - _checkProvisionTokens(indexer); - emit ServiceProviderRegistered(indexer); } @@ -117,8 +122,14 @@ contract SubgraphService is function startService( address indexer, bytes calldata data - ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { - _checkProvisionTokens(indexer); + ) + external + override + onlyProvisionAuthorized(indexer) + onlyValidProvision(indexer) + onlyRegisteredIndexer(indexer) + whenNotPaused + { (bytes32 subgraphDeploymentId, uint256 tokens, address allocationId, bytes memory allocationProof) = abi.decode( data, (bytes32, uint256, address, bytes) @@ -140,8 +151,13 @@ contract SubgraphService is address indexer, address allocationId, uint256 tokens - ) external onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { - _checkProvisionTokens(indexer); + ) + external + onlyProvisionAuthorized(indexer) + onlyValidProvision(indexer) + onlyRegisteredIndexer(indexer) + whenNotPaused + { _resizeAllocation(allocationId, tokens, maximumDelegationRatio); } @@ -149,8 +165,7 @@ contract SubgraphService is address indexer, IGraphPayments.PaymentTypes paymentType, bytes calldata data - ) external override onlyRegisteredIndexer(indexer) whenNotPaused { - _checkProvisionTokens(indexer); + ) external override onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { uint256 paymentCollected = 0; if (paymentType == IGraphPayments.PaymentTypes.QueryFee) { From 3b39aa5133abfa4416c8cc6cfaaa8ee258f31f55 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 23 May 2024 11:31:22 -0300 Subject: [PATCH 049/277] fix: renamed error, move code to trigger revert --- .../contracts/payments/GraphPayments.sol | 22 ++++++++------- .../horizon/test/payments/GraphPayments.t.sol | 28 ++++++++++++++++++- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 8fddc6a07..c5818ca0c 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -30,7 +30,7 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora error GraphPaymentsNotThawing(); error GraphPaymentsStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); error GraphPaymentsCollectorNotAuthorized(address sender, address dataService); - error GraphPaymentsCollectorInsufficientAmount(uint256 available, uint256 required); + error GraphPaymentsInsufficientAmount(uint256 available, uint256 required); // -- Events -- @@ -54,25 +54,27 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora ) external { _graphToken().pullTokens(msg.sender, tokens); - // Pay protocol cut + // Calculate cuts uint256 tokensProtocol = (tokens * PROTOCOL_PAYMENT_CUT) / MAX_PPM; + uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, uint8(paymentType)); + uint256 tokensDelegationPool = (tokens * delegationFeeCut) / MAX_PPM; + uint256 totalCut = tokensProtocol + tokensDataService + tokensDelegationPool; + if (totalCut > tokens) { + revert GraphPaymentsInsufficientAmount(tokens, totalCut); + } + + // Pay protocol cut _graphToken().burnTokens(tokensProtocol); // Pay data service cut _graphToken().pushTokens(dataService, tokensDataService); - // Get delegation cut - uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, uint8(paymentType)); - uint256 tokensDelegationPool = (tokens * delegationFeeCut) / MAX_PPM; + // Pay delegators if (tokensDelegationPool > 0) { _graphStaking().addToDelegationPool(receiver, dataService, tokensDelegationPool); } - // Pay the rest to the receiver - uint256 totalCut = tokensProtocol + tokensDataService + tokensDelegationPool; - if (totalCut > tokens) { - revert GraphPaymentsCollectorInsufficientAmount(tokens, totalCut); - } + // Pay receiver uint256 tokensReceiverRemaining = tokens - totalCut; _graphToken().pushTokens(receiver, tokensReceiverRemaining); diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 74f255d9c..519f6e105 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -9,7 +9,10 @@ import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaki contract GraphPaymentsTest is HorizonStakingSharedTest { - function testCollect(uint256 amount, uint256 tokensDataService) public useProvision(amount, 0, 0) useDelegationFeeCut(0, 100000) { + function testCollect( + uint256 amount, + uint256 tokensDataService + ) public useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); @@ -35,4 +38,27 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { uint256 delegatorBalance = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(delegatorBalance, tokensDelegatoion); } + + function testCollect_RevertWhen_InsufficientAmount( + uint256 amount, + uint256 tokensDataService + ) public useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { + vm.assume(tokensDataService <= 10_000_000_000 ether); + vm.assume(tokensDataService > amount); + + address escrowAddress = address(escrow); + mint(escrowAddress, amount); + vm.startPrank(escrowAddress); + approve(address(payments), amount); + + bytes memory expectedError; + { + uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; + uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; + uint256 requiredAmount = tokensDataService + tokensProtocol + tokensDelegatoion; + expectedError = abi.encodeWithSignature("GraphPaymentsInsufficientAmount(uint256,uint256)", amount, requiredAmount); + } + vm.expectRevert(expectedError); + payments.collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); + } } From 3a66efa829d081494b2ecb69d9a61f727d4cc8c0 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 23 May 2024 11:34:33 -0300 Subject: [PATCH 050/277] fix: removed unwanted import --- packages/horizon/contracts/data-service/GraphDirectory.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index 805136db1..f05d9db66 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -16,7 +16,6 @@ import { IGraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/IG import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; -import "forge-std/console.sol"; /** * @title GraphDirectory contract * @notice This contract is meant to be inherited by other contracts that From ac5546d2c1e7fba15fc5cb0892facf814c770b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 12:15:34 -0300 Subject: [PATCH 051/277] chore: enforce consistent variable naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cut: for PPM percentages - tokens: for token amounts Signed-off-by: Tomás Migone --- .../extensions/DataServiceRescuable.sol | 22 ++--- .../extensions/IDataServiceRescuable.sol | 4 +- .../contracts/interfaces/IGraphToken.sol | 6 +- .../interfaces/IHorizonStakingBase.sol | 6 +- .../contracts/interfaces/IPaymentsEscrow.sol | 8 +- .../contracts/libraries/TokenUtils.sol | 24 ++--- .../horizon/contracts/mocks/MockGRTToken.sol | 10 +-- .../contracts/payments/GraphPayments.sol | 4 +- .../contracts/payments/PaymentsEscrow.sol | 67 +++++++------- .../payments/collectors/TAPCollector.sol | 4 +- .../contracts/staking/HorizonStaking.sol | 20 ++--- .../staking/HorizonStakingExtension.sol | 30 +++---- .../staking/StakingBackwardsCompatibility.sol | 18 ++-- packages/horizon/test/escrow/collect.t.sol | 4 +- packages/horizon/test/escrow/collector.t.sol | 2 +- packages/horizon/test/escrow/thaw.t.sol | 4 +- .../horizon/test/payments/GraphPayments.t.sol | 2 +- .../contracts/DisputeManager.sol | 88 +++++++++---------- .../contracts/DisputeManagerStorage.sol | 4 +- .../contracts/SubgraphService.sol | 11 ++- .../contracts/interfaces/IDisputeManager.sol | 6 +- .../contracts/interfaces/ISubgraphService.sol | 4 +- .../test/DisputeManager.t.sol | 1 - .../test/mocks/MockHorizonStaking.sol | 8 +- .../test/mocks/MockRewardsManager.sol | 26 +++--- 25 files changed, 187 insertions(+), 196 deletions(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index b345a8683..45a1cd4f9 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -21,7 +21,7 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { /** * @dev Tokens rescued by the user */ - event TokensRescued(address indexed from, address indexed to, uint256 amount); + event TokensRescued(address indexed from, address indexed to, uint256 tokens); event RescuerSet(address indexed account, bool allowed); error DataServiceRescuableCannotRescueZero(); @@ -34,12 +34,12 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { _; } - function rescueGRT(address to, uint256 amount) external onlyRescuer { - _rescueTokens(to, address(_graphToken()), amount); + function rescueGRT(address to, uint256 tokens) external onlyRescuer { + _rescueTokens(to, address(_graphToken()), tokens); } - function rescueETH(address payable to, uint256 amount) external onlyRescuer { - _rescueTokens(to, Denominations.NATIVE_TOKEN, amount); + function rescueETH(address payable to, uint256 tokens) external onlyRescuer { + _rescueTokens(to, Denominations.NATIVE_TOKEN, tokens); } function _setRescuer(address _rescuer, bool _allowed) internal { @@ -51,14 +51,14 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { * @dev Allows rescuing tokens sent to this contract * @param _to Destination address to send the tokens * @param _token Address of the token being rescued - * @param _amount Amount of tokens to pull + * @param _tokens Amount of tokens to pull */ - function _rescueTokens(address _to, address _token, uint256 _amount) internal { - if (_amount == 0) revert DataServiceRescuableCannotRescueZero(); + function _rescueTokens(address _to, address _token, uint256 _tokens) internal { + if (_tokens == 0) revert DataServiceRescuableCannotRescueZero(); - if (Denominations.isNativeToken(_token)) payable(_to).transfer(_amount); - else SafeERC20.safeTransfer(IERC20(_token), _to, _amount); + if (Denominations.isNativeToken(_token)) payable(_to).transfer(_tokens); + else SafeERC20.safeTransfer(IERC20(_token), _to, _tokens); - emit TokensRescued(msg.sender, _to, _amount); + emit TokensRescued(msg.sender, _to, _tokens); } } diff --git a/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol index ee379315c..18eee452d 100644 --- a/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol @@ -4,6 +4,6 @@ pragma solidity ^0.8.24; import { IDataService } from "../../interfaces/IDataService.sol"; interface IDataServiceRescuable is IDataService { - function rescueGRT(address to, uint256 amount) external; - function rescueETH(address payable to, uint256 amount) external; + function rescueGRT(address to, uint256 tokens) external; + function rescueETH(address payable to, uint256 tokens) external; } diff --git a/packages/horizon/contracts/interfaces/IGraphToken.sol b/packages/horizon/contracts/interfaces/IGraphToken.sol index d00e81fc1..cb0b6cae6 100644 --- a/packages/horizon/contracts/interfaces/IGraphToken.sol +++ b/packages/horizon/contracts/interfaces/IGraphToken.sol @@ -7,11 +7,11 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IGraphToken is IERC20 { // -- Mint and Burn -- - function burn(uint256 amount) external; + function burn(uint256 tokens) external; - function burnFrom(address from, uint256 amount) external; + function burnFrom(address from, uint256 tokens) external; - function mint(address to, uint256 amount) external; + function mint(address to, uint256 tokens) external; // -- Mint Admin -- diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol index 41f1ae1df..3cef3e193 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol @@ -64,7 +64,7 @@ interface IHorizonStakingBase is IHorizonStakingTypes { event DelegationSlashingSkipped(address indexed serviceProvider, address indexed verifier, uint256 tokens); - event VerifierCutSent( + event VerifierTokensSent( address indexed serviceProvider, address indexed verifier, address indexed destination, @@ -181,8 +181,8 @@ interface IHorizonStakingBase is IHorizonStakingTypes { function slash( address serviceProvider, uint256 tokens, - uint256 verifierCutAmount, - address verifierCutDestination + uint256 tokensVerifier, + address verifierDestination ) external; /** diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index cd7665e73..de3f0af06 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -6,22 +6,22 @@ import { IGraphPayments } from "./IGraphPayments.sol"; interface IPaymentsEscrow { struct EscrowAccount { uint256 balance; // Total escrow balance for a sender-receiver pair - uint256 amountThawing; // Amount of escrow currently being thawed + uint256 tokensThawing; // Amount of escrow currently being thawed uint256 thawEndTimestamp; // Timestamp at which thawing period ends (zero if not thawing) } // Collector struct Collector { bool authorized; - uint256 amount; + uint256 allowance; uint256 thawEndTimestamp; } // Deposit funds into the escrow for a receiver - function deposit(address receiver, uint256 amount) external; + function deposit(address receiver, uint256 tokens) external; // Requests to thaw a specific amount of escrow from a receiver's escrow account - function thaw(address receiver, uint256 amount) external; + function thaw(address receiver, uint256 tokens) external; // Withdraws all thawed escrow from a receiver's escrow account function withdraw(address receiver) external; diff --git a/packages/horizon/contracts/libraries/TokenUtils.sol b/packages/horizon/contracts/libraries/TokenUtils.sol index 07b267451..30903d6ae 100644 --- a/packages/horizon/contracts/libraries/TokenUtils.sol +++ b/packages/horizon/contracts/libraries/TokenUtils.sol @@ -15,11 +15,11 @@ library TokenUtils { * @dev 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 + * @param _tokens Amount of tokens to transfer */ - function pullTokens(IGraphToken _graphToken, address _from, uint256 _amount) internal { - if (_amount > 0) { - require(_graphToken.transferFrom(_from, address(this), _amount), "!transfer"); + function pullTokens(IGraphToken _graphToken, address _from, uint256 _tokens) internal { + if (_tokens > 0) { + require(_graphToken.transferFrom(_from, address(this), _tokens), "!transfer"); } } @@ -27,22 +27,22 @@ library TokenUtils { * @dev 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 + * @param _tokens Amount of tokens to transfer */ - function pushTokens(IGraphToken _graphToken, address _to, uint256 _amount) internal { - if (_amount > 0) { - require(_graphToken.transfer(_to, _amount), "!transfer"); + function pushTokens(IGraphToken _graphToken, address _to, uint256 _tokens) internal { + if (_tokens > 0) { + require(_graphToken.transfer(_to, _tokens), "!transfer"); } } /** * @dev Burn tokens held by this contract. * @param _graphToken Token to burn - * @param _amount Amount of tokens to burn + * @param _tokens Amount of tokens to burn */ - function burnTokens(IGraphToken _graphToken, uint256 _amount) internal { - if (_amount > 0) { - _graphToken.burn(_amount); + function burnTokens(IGraphToken _graphToken, uint256 _tokens) internal { + if (_tokens > 0) { + _graphToken.burn(_tokens); } } } diff --git a/packages/horizon/contracts/mocks/MockGRTToken.sol b/packages/horizon/contracts/mocks/MockGRTToken.sol index 1212f3e70..7d7e1cc9e 100644 --- a/packages/horizon/contracts/mocks/MockGRTToken.sol +++ b/packages/horizon/contracts/mocks/MockGRTToken.sol @@ -7,10 +7,10 @@ import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToke contract MockGRTToken is ERC20, IGraphToken { constructor() ERC20("Graph Token", "GRT") {} - function burn(uint256 amount) external {} + function burn(uint256 tokens) external {} - function burnFrom(address from, uint256 amount) external { - _burn(from, amount); + function burnFrom(address from, uint256 tokens) external { + _burn(from, tokens); } // -- Mint Admin -- @@ -41,7 +41,7 @@ contract MockGRTToken is ERC20, IGraphToken { function isMinter(address account) external view returns (bool) {} - function mint(address to, uint256 amount) public { - _mint(to, amount); + function mint(address to, uint256 tokens) public { + _mint(to, tokens); } } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index c5818ca0c..84e4fabd2 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -30,7 +30,7 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora error GraphPaymentsNotThawing(); error GraphPaymentsStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); error GraphPaymentsCollectorNotAuthorized(address sender, address dataService); - error GraphPaymentsInsufficientAmount(uint256 available, uint256 required); + error GraphPaymentsInsufficientTokens(uint256 available, uint256 required); // -- Events -- @@ -60,7 +60,7 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora uint256 tokensDelegationPool = (tokens * delegationFeeCut) / MAX_PPM; uint256 totalCut = tokensProtocol + tokensDataService + tokensDelegationPool; if (totalCut > tokens) { - revert GraphPaymentsInsufficientAmount(tokens, totalCut); + revert GraphPaymentsInsufficientTokens(tokens, totalCut); } // Pay protocol cut diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 9404190be..6d7e82d11 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -43,7 +43,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { address indexed payer, address indexed receiver, uint256 tokens, - uint256 totalAmountThawing, + uint256 totalTokensThawing, uint256 thawEndTimestamp ); event Withdraw(address indexed payer, address indexed receiver, uint256 tokens); @@ -53,14 +53,13 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { error GraphEscrowNotGraphPayments(); error GraphEscrowInputsLengthMismatch(); - error GraphEscrowInsufficientThawAmount(); - error GraphEscrowInsufficientAmount(uint256 available, uint256 required); + error GraphEscrowInsufficientTokensThawing(); + error GraphEscrowInsufficientBalance(uint256 available, uint256 required); error GraphEscrowNotThawing(); error GraphEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); error GraphEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); error GraphEscrowCollectorNotAuthorized(address sender, address dataService); - error GraphEscrowCollectorInsufficientAmount(uint256 available, uint256 required); - + error GraphEscrowInsufficientAllowance(uint256 available, uint256 required); error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); // -- Constructor -- @@ -83,14 +82,14 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // approve a data service to collect funds - function approveCollector(address dataService, uint256 amount) external { + function approveCollector(address dataService, uint256 tokens) external { Collector storage collector = authorizedCollectors[msg.sender][dataService]; - if (collector.amount > amount) { - revert GraphEscrowCollectorInsufficientAmount(collector.amount, amount); + if (collector.allowance > tokens) { + revert GraphEscrowInsufficientAllowance(collector.allowance, tokens); } collector.authorized = true; - collector.amount = amount; + collector.allowance = tokens; emit AuthorizedCollector(msg.sender, dataService); } @@ -129,39 +128,39 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // Deposit funds into the escrow for a receiver - function deposit(address receiver, uint256 amount) external { - escrowAccounts[msg.sender][receiver].balance += amount; - _graphToken().pullTokens(msg.sender, amount); - emit Deposit(msg.sender, receiver, amount); + function deposit(address receiver, uint256 tokens) external { + escrowAccounts[msg.sender][receiver].balance += tokens; + _graphToken().pullTokens(msg.sender, tokens); + emit Deposit(msg.sender, receiver, tokens); } // Requests to thaw a specific amount of escrow from a receiver's escrow account - function thaw(address receiver, uint256 amount) external { + function thaw(address receiver, uint256 tokens) external { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; - if (amount == 0) { + if (tokens == 0) { // if amount thawing is zero and requested amount is zero this is an invalid request. // otherwise if amount thawing is greater than zero and requested amount is zero this // is a cancel thaw request. - if (account.amountThawing == 0) { - revert GraphEscrowInsufficientThawAmount(); + if (account.tokensThawing == 0) { + revert GraphEscrowInsufficientTokensThawing(); } - account.amountThawing = 0; + account.tokensThawing = 0; account.thawEndTimestamp = 0; emit CancelThaw(msg.sender, receiver); return; } // Check if the escrow balance is sufficient - if (account.balance < amount) { - revert GraphEscrowInsufficientAmount({ available: account.balance, required: amount }); + if (account.balance < tokens) { + revert GraphEscrowInsufficientBalance(account.balance, tokens); } // Set amount to thaw - account.amountThawing = amount; + account.tokensThawing = tokens; // Set when the thaw is complete (thawing period number of seconds after current timestamp) account.thawEndTimestamp = block.timestamp + WITHDRAW_ESCROW_THAWING_PERIOD; - emit Thaw(msg.sender, receiver, amount, account.amountThawing, account.thawEndTimestamp); + emit Thaw(msg.sender, receiver, tokens, account.tokensThawing, account.thawEndTimestamp); } // Withdraws all thawed escrow from a receiver's escrow account @@ -179,13 +178,13 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // Amount is the minimum between the amount being thawed and the actual balance - uint256 amount = account.amountThawing > account.balance ? account.balance : account.amountThawing; + uint256 tokens = account.tokensThawing > account.balance ? account.balance : account.tokensThawing; - account.balance -= amount; // Reduce the balance by the withdrawn amount (no underflow risk) - account.amountThawing = 0; + account.balance -= tokens; // Reduce the balance by the withdrawn amount (no underflow risk) + account.tokensThawing = 0; account.thawEndTimestamp = 0; - _graphToken().pushTokens(msg.sender, amount); - emit Withdraw(msg.sender, receiver, amount); + _graphToken().pushTokens(msg.sender, tokens); + emit Withdraw(msg.sender, receiver, tokens); } // Collect from escrow for a receiver using sender's deposit @@ -204,18 +203,18 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { revert GraphEscrowCollectorNotAuthorized(payer, msg.sender); } - if (collector.amount < tokens) { - revert GraphEscrowCollectorInsufficientAmount(collector.amount, tokens); + if (collector.allowance < tokens) { + revert GraphEscrowInsufficientAllowance(collector.allowance, tokens); } // Reduce amount from approved collector - collector.amount -= tokens; + collector.allowance -= tokens; // Collect tokens from GraphEscrow up to amount available EscrowAccount storage account = escrowAccounts[payer][receiver]; - uint256 availableAmount = account.balance - account.amountThawing; - if (availableAmount < tokens) { - revert GraphEscrowInsufficientAmount(availableAmount, tokens); + uint256 availableTokens = account.balance - account.tokensThawing; + if (availableTokens < tokens) { + revert GraphEscrowInsufficientBalance(availableTokens, tokens); } account.balance -= tokens; @@ -237,6 +236,6 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // Get the balance of a sender-receiver pair function getBalance(address payer, address receiver) external view returns (uint256) { EscrowAccount storage account = escrowAccounts[payer][receiver]; - return account.balance - account.amountThawing; + return account.balance - account.tokensThawing; } } diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index f0fb31077..1a0a66ab7 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -53,7 +53,7 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. */ function collect(IGraphPayments.PaymentTypes paymentType, bytes memory data) external returns (uint256) { - (SignedRAV memory signedRAV, uint256 percentageDataService) = abi.decode(data, (SignedRAV, uint256)); + (SignedRAV memory signedRAV, uint256 dataServiceCut) = abi.decode(data, (SignedRAV, uint256)); if (signedRAV.rav.dataService != msg.sender) { revert TAPCollectorCallerNotDataService(msg.sender, signedRAV.rav.dataService); @@ -70,7 +70,7 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { } uint256 tokensToCollect = tokensRAV - tokensAlreadyCollected; - uint256 tokensDataService = tokensToCollect.mulPPM(percentageDataService); + uint256 tokensDataService = tokensToCollect.mulPPM(dataServiceCut); if (tokensToCollect > 0) { _graphPaymentsEscrow().collect( diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 95c297ffd..6aeb5d19a 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -59,7 +59,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV error HorizonStakingInsufficientCapacityForLegacyAllocations(); error HorizonStakingTooManyThawRequests(); error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); - error HorizonStakingSlippageProtection(uint256 minExpectedAmount, uint256 actualAmount); + error HorizonStakingSlippageProtection(uint256 minExpectedShares, uint256 actualShares); modifier onlyAuthorized(address serviceProvider, address verifier) { if (!isAuthorized(msg.sender, serviceProvider, verifier)) { @@ -375,14 +375,14 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV * provider's provisioned self-stake, the delegation slashing is skipped without reverting. * @param serviceProvider The service provider to slash * @param tokens The amount of tokens to slash - * @param verifierCutAmount The amount of tokens to transfer instead of burning - * @param verifierCutDestination The address to transfer the verifier cut to + * @param tokensVerifier The amount of tokens to transfer instead of burning + * @param verifierDestination The address to transfer the verifier cut to */ function slash( address serviceProvider, uint256 tokens, - uint256 verifierCutAmount, - address verifierCutDestination + uint256 tokensVerifier, + address verifierDestination ) external override notPartialPaused { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; @@ -393,12 +393,12 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV uint256 tokensToSlash = tokens; uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); if (providerTokensSlashed > 0) { - require((prov.tokens * prov.maxVerifierCut) / MAX_PPM >= verifierCutAmount, "verifier cut too high"); - if (verifierCutAmount > 0) { - _graphToken().pushTokens(verifierCutDestination, verifierCutAmount); - emit VerifierCutSent(serviceProvider, verifier, verifierCutDestination, verifierCutAmount); + require((prov.tokens * prov.maxVerifierCut) / MAX_PPM >= tokensVerifier, "verifier cut too high"); + if (tokensVerifier > 0) { + _graphToken().pushTokens(verifierDestination, tokensVerifier); + emit VerifierTokensSent(serviceProvider, verifier, verifierDestination, tokensVerifier); } - _graphToken().burnTokens(providerTokensSlashed - verifierCutAmount); + _graphToken().burnTokens(providerTokensSlashed - tokensVerifier); uint256 provisionFractionSlashed = (providerTokensSlashed * FIXED_POINT_PRECISION) / prov.tokens; // TODO check for rounding issues prov.tokensThawing = diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 7142fbd31..e7b0e744d 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -71,12 +71,12 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas * or a delegator's delegation. * See L1MessageCodes in IL2Staking for the supported messages. * @param from Token sender in L1 - * @param amount Amount of tokens that were transferred + * @param tokens Amount of tokens that were transferred * @param data ABI-encoded callhook data which must include a uint8 code and either a ReceiveIndexerStakeData or ReceiveDelegationData struct. */ function onTokenTransfer( address from, - uint256 amount, + uint256 tokens, bytes calldata data ) external override notPartialPaused onlyL2Gateway { require(from == _counterpartStakingAddress, "ONLY_L1_STAKING_THROUGH_BRIDGE"); @@ -87,13 +87,13 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas functionData, (IL2StakingTypes.ReceiveIndexerStakeData) ); - _receiveIndexerStake(amount, indexerData); + _receiveIndexerStake(tokens, indexerData); } else if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE)) { IL2StakingTypes.ReceiveDelegationData memory delegationData = abi.decode( functionData, (IL2StakingTypes.ReceiveDelegationData) ); - _receiveDelegation(amount, delegationData); + _receiveDelegation(tokens, delegationData); } else { revert("INVALID_CODE"); } @@ -210,16 +210,16 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas * @dev 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 + * @param _tokens Amount of tokens that were transferred * @param _indexerData struct containing the indexer's address */ function _receiveIndexerStake( - uint256 _amount, + uint256 _tokens, IL2StakingTypes.ReceiveIndexerStakeData memory _indexerData ) internal { address indexer = _indexerData.indexer; // Deposit tokens into the indexer stake - _stake(indexer, _amount); + _stake(indexer, _tokens); } /** @@ -227,11 +227,11 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas * 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. - * @param _amount Amount of tokens that were transferred + * @param _tokens Amount of tokens that were transferred * @param _delegationData struct containing the delegator's address and the indexer's address */ function _receiveDelegation( - uint256 _amount, + uint256 _tokens, IL2StakingTypes.ReceiveDelegationData memory _delegationData ) internal { // Get the delegation pool of the indexer @@ -239,23 +239,23 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas Delegation storage delegation = pool.delegators[_delegationData.delegator]; // Calculate shares to issue (without applying any delegation tax) - uint256 shares = (pool.tokens == 0) ? _amount : ((_amount * pool.shares) / pool.tokens); + uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / pool.tokens); - if (shares == 0 || _amount < MINIMUM_DELEGATION) { + if (shares == 0 || _tokens < MINIMUM_DELEGATION) { // If no shares would be issued (probably a rounding issue or attack), // or if the amount is under the minimum delegation (which could be part of a rounding attack), // return the tokens to the delegator - _graphToken().transfer(_delegationData.delegator, _amount); - emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _amount); + _graphToken().transfer(_delegationData.delegator, _tokens); + emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _tokens); } else { // Update the delegation pool - pool.tokens = pool.tokens + _amount; + pool.tokens = pool.tokens + _tokens; pool.shares = pool.shares + shares; // Update the individual delegation delegation.shares = delegation.shares + shares; - emit StakeDelegated(_delegationData.indexer, _delegationData.delegator, _amount, shares); + emit StakeDelegated(_delegationData.indexer, _delegationData.delegator, _tokens, shares); } } } diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 737fd8d5f..66c088e02 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -313,20 +313,20 @@ abstract contract StakingBackwardsCompatibility is /** * @dev Send rewards to the appropriate destination. - * @param _amount Number of rewards tokens + * @param _tokens Number of rewards tokens * @param _beneficiary Address of the beneficiary of rewards * @param _restake Whether to restake or not */ - function _sendRewards(uint256 _amount, address _beneficiary, bool _restake) private { - if (_amount == 0) return; + function _sendRewards(uint256 _tokens, address _beneficiary, bool _restake) private { + if (_tokens == 0) return; if (_restake) { // Restake to place fees into the indexer stake - _stake(_beneficiary, _amount); + _stake(_beneficiary, _tokens); } else { // Transfer funds to the beneficiary's designated rewards destination if set address destination = __DEPRECATED_rewardsDestination[_beneficiary]; - _graphToken().pushTokens(destination == address(0) ? _beneficiary : destination, _amount); + _graphToken().pushTokens(destination == address(0) ? _beneficiary : destination, _tokens); } } @@ -435,25 +435,25 @@ abstract contract StakingBackwardsCompatibility is * This function transfer curation fees to the Curation contract by calling Curation.collect * @param _subgraphDeploymentID Subgraph deployment to which the curation fees are related * @param _tokens Total tokens received used to calculate the amount of fees to collect - * @param _curationPercentage Percentage of tokens to collect as fees + * @param _curationCut Percentage of tokens to collect as fees * @return Amount of curation fees */ function _collectCurationFees( bytes32 _subgraphDeploymentID, uint256 _tokens, - uint256 _curationPercentage + uint256 _curationCut ) private returns (uint256) { if (_tokens == 0) { return 0; } ICuration curation = _graphCuration(); - bool isCurationEnabled = _curationPercentage > 0 && address(curation) != address(0); + bool isCurationEnabled = _curationCut > 0 && address(curation) != address(0); if (isCurationEnabled && curation.isCurated(_subgraphDeploymentID)) { // Calculate the tokens after curation fees first, and subtact that, // to prevent curation fees from rounding down to zero - uint256 tokensAfterCurationFees = ((uint256(MAX_PPM) - _curationPercentage) * _tokens) / MAX_PPM; + uint256 tokensAfterCurationFees = ((uint256(MAX_PPM) - _curationCut) * _tokens) / MAX_PPM; uint256 curationFees = _tokens - tokensAfterCurationFees; if (curationFees > 0) { // Transfer and call collect() diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 4c66cfc0c..9893d3aee 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -44,7 +44,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { vm.assume(insufficientAmount < amount); changePrank(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", insufficientAmount, amount); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAllowance(uint256,uint256)", insufficientAmount, amount); vm.expectRevert(expectedError); escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); } @@ -56,7 +56,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { vm.assume(insufficientAmount < amount); changePrank(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", insufficientAmount, amount); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientBalance(uint256,uint256)", insufficientAmount, amount); vm.expectRevert(expectedError); escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); vm.stopPrank(); diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index c87545b1a..9274f6f9d 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -20,7 +20,7 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { uint256 smallerAmount ) public useGateway useCollector(amount) { vm.assume(smallerAmount < amount); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorInsufficientAmount(uint256,uint256)", amount, smallerAmount); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAllowance(uint256,uint256)", amount, smallerAmount); vm.expectRevert(expectedError); escrow.approveCollector(users.verifier, smallerAmount); } diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index a9d95460b..287400d8f 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -18,7 +18,7 @@ contract GraphEscrowThawTest is GraphEscrowTest { function testThaw_RevertWhen_InsufficientThawAmount( uint256 amount ) public useGateway useDeposit(amount) { - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientThawAmount()"); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientTokensThawing()"); vm.expectRevert(expectedError); escrow.thaw(users.indexer, 0); } @@ -27,7 +27,7 @@ contract GraphEscrowThawTest is GraphEscrowTest { uint256 amount ) public useGateway useDeposit(amount) { uint256 overAmount = amount + 1; - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAmount(uint256,uint256)", amount, overAmount); + bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientBalance(uint256,uint256)", amount, overAmount); vm.expectRevert(expectedError); escrow.thaw(users.indexer, overAmount); } diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 519f6e105..78e868cae 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -56,7 +56,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; uint256 requiredAmount = tokensDataService + tokensProtocol + tokensDelegatoion; - expectedError = abi.encodeWithSignature("GraphPaymentsInsufficientAmount(uint256,uint256)", amount, requiredAmount); + expectedError = abi.encodeWithSignature("GraphPaymentsInsufficientTokens(uint256,uint256)", amount, requiredAmount); } vm.expectRevert(expectedError); payments.collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index ac0320651..69190b27f 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -49,8 +49,8 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM event ArbitratorSet(address arbitrator); event DisputePeriodSet(uint64 disputePeriod); event MinimumDepositSet(uint256 minimumDeposit); - event MaxSlashingPercentageSet(uint32 maxSlashingPercentage); - event FishermanRewardPercentageSet(uint32 fishermanRewardPercentage); + event MaxSlashingCutSet(uint32 maxSlashingCut); + event FishermanRewardCutSet(uint32 fishermanRewardCut); event SubgraphServiceSet(address indexed subgraphService); /** @@ -124,9 +124,9 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM error DisputeManagerZeroTokens(); error DisputeManagerInvalidDispute(bytes32 disputeId); error DisputeManagerInvalidMinimumDeposit(uint256 minimumDeposit); - error DisputeManagerInvalidFishermanReward(uint32 percentage); - error DisputeManagerInvalidMaxSlashingPercentage(uint32 maxSlashingPercentage); - error DisputeManagerInvalidSlashAmount(uint256 slashAmount); + error DisputeManagerInvalidFishermanReward(uint32 cut); + error DisputeManagerInvalidMaxSlashingCut(uint32 maxSlashingCut); + error DisputeManagerInvalidTokensSlash(uint256 tokensSlash); error DisputeManagerInvalidDisputeStatus(IDisputeManager.DisputeStatus status); error DisputeManagerInsufficientDeposit(uint256 deposit, uint256 minimumDeposit); error DisputeManagerDisputeAlreadyCreated(bytes32 disputeId); @@ -185,23 +185,23 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @param arbitrator Arbitrator role * @param disputePeriod Dispute period in seconds * @param minimumDeposit Minimum deposit required to create a Dispute - * @param fishermanRewardPercentage Percent of slashed funds for fisherman (ppm) - * @param maxSlashingPercentage Maximum percentage of indexer stake that can be slashed (ppm) + * @param fishermanRewardCut_ Percent of slashed funds for fisherman (ppm) + * @param maxSlashingCut_ Maximum percentage of indexer stake that can be slashed (ppm) */ constructor( address controller, address arbitrator, uint64 disputePeriod, uint256 minimumDeposit, - uint32 fishermanRewardPercentage, - uint32 maxSlashingPercentage + uint32 fishermanRewardCut_, + uint32 maxSlashingCut_ ) Ownable(msg.sender) GraphDirectory(controller) { // Settings _setArbitrator(arbitrator); _setDisputePeriod(disputePeriod); _setMinimumDeposit(minimumDeposit); - _setFishermanRewardPercentage(fishermanRewardPercentage); - _setMaxSlashingPercentage(maxSlashingPercentage); + _setFishermanRewardCut(fishermanRewardCut_); + _setMaxSlashingCut(maxSlashingCut_); } /** @@ -297,11 +297,11 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * 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 - * @param slashAmount Amount of tokens to slash from the indexer + * @param tokensSlash Amount of tokens to slash from the indexer */ function acceptDispute( bytes32 disputeId, - uint256 slashAmount + uint256 tokensSlash ) external override onlyArbitrator onlyPendingDispute(disputeId) { Dispute storage dispute = disputes[disputeId]; @@ -309,7 +309,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM dispute.status = IDisputeManager.DisputeStatus.Accepted; // Slash - uint256 tokensToReward = _slashIndexer(dispute.indexer, slashAmount); + uint256 tokensToReward = _slashIndexer(dispute.indexer, tokensSlash); // Give the fisherman their reward and their deposit back _graphToken().pushTokens(dispute.fisherman, tokensToReward + dispute.deposit); @@ -395,18 +395,18 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM /** * @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 + * @param fishermanRewardCut_ Reward as a percentage of indexer stake */ - function setFishermanRewardPercentage(uint32 percentage) external override onlyOwner { - _setFishermanRewardPercentage(percentage); + function setFishermanRewardCut(uint32 fishermanRewardCut_) external override onlyOwner { + _setFishermanRewardCut(fishermanRewardCut_); } /** * @dev Set the maximum percentage that can be used for slashing indexers. - * @param maxSlashingPercentage Max percentage slashing for disputes + * @param maxSlashingCut_ Max percentage slashing for disputes */ - function setMaxSlashingPercentage(uint32 maxSlashingPercentage) external override onlyOwner { - _setMaxSlashingPercentage(maxSlashingPercentage); + function setMaxSlashingCut(uint32 maxSlashingCut_) external override onlyOwner { + _setMaxSlashingCut(maxSlashingCut_); } /** @@ -435,7 +435,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @return Verifier cut in percentage (ppm) */ function getVerifierCut() external view returns (uint32) { - return fishermanRewardPercentage; + return fishermanRewardCut; } /** @@ -667,9 +667,9 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @dev Make the subgraph service 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 _slashAmount Amount of tokens to slash from the indexer + * @param _tokensSlash Amount of tokens to slash from the indexer */ - function _slashIndexer(address _indexer, uint256 _slashAmount) private returns (uint256 rewardsAmount) { + function _slashIndexer(address _indexer, uint256 _tokensSlash) private returns (uint256) { // Get slashable amount for indexer IHorizonStaking.Provision memory provision = _graphStaking().getProvision(_indexer, address(subgraphService)); IHorizonStaking.DelegationPool memory pool = _graphStaking().getDelegationPool( @@ -679,22 +679,22 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM uint256 totalProvisionTokens = provision.tokens + pool.tokens; // slashable tokens // Get slash amount - uint256 maxSlashAmount = uint256(maxSlashingPercentage).mulPPM(totalProvisionTokens); - if (_slashAmount == 0) { - revert DisputeManagerInvalidSlashAmount(_slashAmount); + uint256 maxTokensSlash = uint256(maxSlashingCut).mulPPM(totalProvisionTokens); + if (_tokensSlash == 0) { + revert DisputeManagerInvalidTokensSlash(_tokensSlash); } - if (_slashAmount > maxSlashAmount) { - revert DisputeManagerInvalidSlashAmount(_slashAmount); + if (_tokensSlash > maxTokensSlash) { + revert DisputeManagerInvalidTokensSlash(_tokensSlash); } // Rewards amount can only be extracted from service poriver tokens so // we grab the minimum between the slash amount and indexer's tokens - uint256 maxRewardableTokens = Math.min(_slashAmount, provision.tokens); - rewardsAmount = uint256(fishermanRewardPercentage).mulPPM(maxRewardableTokens); + uint256 maxRewardableTokens = Math.min(_tokensSlash, provision.tokens); + uint256 tokensRewards = uint256(fishermanRewardCut).mulPPM(maxRewardableTokens); - subgraphService.slash(_indexer, abi.encode(_slashAmount, rewardsAmount)); - return rewardsAmount; + subgraphService.slash(_indexer, abi.encode(_tokensSlash, tokensRewards)); + return tokensRewards; } /** @@ -739,28 +739,28 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM /** * @dev Internal: 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 + * @param _fishermanRewardCut Reward as a percentage of indexer stake */ - function _setFishermanRewardPercentage(uint32 _percentage) private { + function _setFishermanRewardCut(uint32 _fishermanRewardCut) private { // Must be within 0% to 100% (inclusive) - if (!PPMMath.isValidPPM(_percentage)) { - revert DisputeManagerInvalidFishermanReward(_percentage); + if (!PPMMath.isValidPPM(_fishermanRewardCut)) { + revert DisputeManagerInvalidFishermanReward(_fishermanRewardCut); } - fishermanRewardPercentage = _percentage; - emit FishermanRewardPercentageSet(fishermanRewardPercentage); + fishermanRewardCut = _fishermanRewardCut; + emit FishermanRewardCutSet(fishermanRewardCut); } /** * @dev Internal: Set the maximum percentage that can be used for slashing indexers. - * @param _maxSlashingPercentage Max percentage slashing for disputes + * @param _maxSlashingCut Max percentage slashing for disputes */ - function _setMaxSlashingPercentage(uint32 _maxSlashingPercentage) private { + function _setMaxSlashingCut(uint32 _maxSlashingCut) private { // Must be within 0% to 100% (inclusive) - if (!PPMMath.isValidPPM(_maxSlashingPercentage)) { - revert DisputeManagerInvalidMaxSlashingPercentage(_maxSlashingPercentage); + if (!PPMMath.isValidPPM(_maxSlashingCut)) { + revert DisputeManagerInvalidMaxSlashingCut(_maxSlashingCut); } - maxSlashingPercentage = _maxSlashingPercentage; - emit MaxSlashingPercentageSet(maxSlashingPercentage); + maxSlashingCut = _maxSlashingCut; + emit MaxSlashingCutSet(maxSlashingCut); } /** diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol index 350d96566..e3af4bf53 100644 --- a/packages/subgraph-service/contracts/DisputeManagerStorage.sol +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -21,11 +21,11 @@ abstract contract DisputeManagerV1Storage { // 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; + uint32 public fishermanRewardCut; // Maximum percentage of indexer stake that can be slashed on a dispute // Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) - uint32 public maxSlashingPercentage; + uint32 public maxSlashingCut; // Disputes created : disputeID => Dispute // disputeID - check creation functions to see how disputeID is built diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 2f8a504fb..e82e7c7e6 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -238,15 +238,14 @@ contract SubgraphService is // Collect from GraphPayments PaymentCuts memory queryFeePaymentCuts = _getQueryFeePaymentCuts(subgraphDeploymentId); - uint256 percentageTotalCut = queryFeePaymentCuts.percentageServiceCut + - queryFeePaymentCuts.percentageCurationCut; + uint256 totalCut = queryFeePaymentCuts.serviceCut + queryFeePaymentCuts.curationCut; uint256 balanceBefore = _graphToken().balanceOf(address(this)); uint256 tokensCollected = _tapCollector().collect( IGraphPayments.PaymentTypes.QueryFee, - abi.encode(signedRav, percentageTotalCut) + abi.encode(signedRav, totalCut) ); - uint256 tokensDataService = tokensCollected.mulPPM(percentageTotalCut); + uint256 tokensDataService = tokensCollected.mulPPM(totalCut); uint256 balanceAfter = _graphToken().balanceOf(address(this)); if (balanceAfter - balanceBefore != tokensDataService) { revert SubgraphServiceInconsistentCollection(balanceBefore, balanceAfter, tokensDataService); @@ -261,7 +260,7 @@ contract SubgraphService is _lockStake(IGraphPayments.PaymentTypes.QueryFee, indexer, tokensToLock, unlockTimestamp); // calculate service and curator cuts - tokensCurators = tokensCollected.mulPPMRoundUp(queryFeePaymentCuts.percentageCurationCut); + tokensCurators = tokensCollected.mulPPMRoundUp(queryFeePaymentCuts.curationCut); tokensSubgraphService = tokensDataService - tokensCurators; if (tokensCurators > 0) { @@ -283,7 +282,7 @@ contract SubgraphService is // Only pay curation fees if the subgraph is curated if (!_curation().isCurated(_subgraphDeploymentId)) { - queryFeePaymentCuts.percentageCurationCut = 0; + queryFeePaymentCuts.curationCut = 0; } return queryFeePaymentCuts; diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index d40750a55..70fe4e7f8 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -44,9 +44,9 @@ interface IDisputeManager { function setMinimumDeposit(uint256 minimumDeposit) external; - function setFishermanRewardPercentage(uint32 percentage) external; + function setFishermanRewardCut(uint32 cut) external; - function setMaxSlashingPercentage(uint32 maxPercentage) external; + function setMaxSlashingCut(uint32 maxCut) external; // -- Dispute -- @@ -59,7 +59,7 @@ interface IDisputeManager { function createIndexingDispute(address allocationId, uint256 deposit) external returns (bytes32); - function acceptDispute(bytes32 disputeId, uint256 slashAmount) external; + function acceptDispute(bytes32 disputeId, uint256 tokensSlash) external; function rejectDispute(bytes32 disputeId) external; diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 4e395fc0b..e1f85ec25 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -14,8 +14,8 @@ interface ISubgraphService is IDataServiceFees { } struct PaymentCuts { - uint128 percentageServiceCut; - uint128 percentageCurationCut; + uint128 serviceCut; + uint128 curationCut; } function resizeAllocation(address indexer, address allocationId, uint256 tokens) external; diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol index 8d338299f..fea4d3ed7 100644 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -64,7 +64,6 @@ contract DisputeManagerTest is Test { staking = new MockHorizonStaking(address(graphToken)); rewardsManager = new MockRewardsManager(); - address payments = address(0xE2); address tapVerifier = address(0xE3); address curation = address(0xE4); diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index b8f722bcf..7b21f25a1 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -96,13 +96,7 @@ contract MockHorizonStaking { return _provisions[verifier][serviceProvider]; } - /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param _operator The address to check for auth - * @param _serviceProvider The service provider on behalf of whom they're claiming to act - * @param _verifier The verifier / data service on which they're claiming to act - */ - function isAuthorized(address _operator, address _serviceProvider, address _verifier) external view returns (bool) { + function isAuthorized(address, address, address) external pure returns (bool) { return true; } diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index 49c284aaa..f2447c7c4 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -8,21 +8,21 @@ import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRew contract MockRewardsManager is IRewardsManager { // -- Config -- - function setIssuancePerBlock(uint256 _issuancePerBlock) external {} + function setIssuancePerBlock(uint256) external {} - function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external {} + function setMinimumSubgraphSignal(uint256) external {} - function setRewardsIssuer(address _rewardsIssuer, bool _allowed) external {} + function setRewardsIssuer(address, bool) external {} // -- Denylist -- - function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external {} + function setSubgraphAvailabilityOracle(address) external {} - function setDenied(bytes32 _subgraphDeploymentID, bool _deny) external {} + function setDenied(bytes32, bool) external {} - function setDeniedMany(bytes32[] calldata _subgraphDeploymentID, bool[] calldata _deny) external {} + function setDeniedMany(bytes32[] calldata, bool[] calldata) external {} - function isDenied(bytes32 _subgraphDeploymentID) external view returns (bool) {} + function isDenied(bytes32) external view returns (bool) {} // -- Getters -- @@ -30,23 +30,23 @@ contract MockRewardsManager is IRewardsManager { function getAccRewardsPerSignal() external view returns (uint256) {} - function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) external view returns (uint256) {} + function getAccRewardsForSubgraph(bytes32) external view returns (uint256) {} - function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID) external view returns (uint256, uint256) {} + function getAccRewardsPerAllocatedToken(bytes32) external view returns (uint256, uint256) {} - function getRewards(address _allocationID) external view returns (uint256) {} + function getRewards(address) external view returns (uint256) {} // -- Updates -- function updateAccRewardsPerSignal() external returns (uint256) {} - function takeRewards(address _allocationID) external returns (uint256) {} + function takeRewards(address) external returns (uint256) {} // -- Hooks -- - function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external returns (uint256) {} + function onSubgraphSignalUpdate(bytes32) external pure returns (uint256) {} - function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) external returns (uint256) { + function onSubgraphAllocationUpdate(bytes32) external pure returns (uint256) { return 0; } } \ No newline at end of file From 187daaf8a96c519c557bb717516b7f60786eab64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 13:02:12 -0300 Subject: [PATCH 052/277] chore: use PPMMath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/GraphDirectory.sol | 6 ++--- .../horizon/contracts/libraries/PPMMath.sol | 8 +++---- .../contracts/payments/GraphPayments.sol | 8 +++---- .../contracts/staking/HorizonStaking.sol | 11 ++++----- .../staking/StakingBackwardsCompatibility.sol | 23 +++++++------------ 5 files changed, 24 insertions(+), 32 deletions(-) diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index f05d9db66..3f50440b2 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -56,11 +56,11 @@ abstract contract GraphDirectory { ICuration graphCuration ); - error GraphDirectoryInvalidZeroAddress(); + error GraphDirectoryInvalidZeroAddress(bytes contractName); constructor(address controller) { if (controller == address(0)) { - revert GraphDirectoryInvalidZeroAddress(); + revert GraphDirectoryInvalidZeroAddress("Controller"); } GRAPH_CONTROLLER = IController(controller); @@ -137,7 +137,7 @@ abstract contract GraphDirectory { function _getContractFromController(bytes memory _contractName) private view returns (address) { address contractAddress = GRAPH_CONTROLLER.getContractProxy(keccak256(_contractName)); if (contractAddress == address(0)) { - revert GraphDirectoryInvalidZeroAddress(); + revert GraphDirectoryInvalidZeroAddress(_contractName); } return contractAddress; } diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index ac0f65252..2129f4a96 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.24; library PPMMath { - /// @notice Maximum value in parts per million (PPM). + /// @notice Maximum value (100%) in parts per million (PPM). uint256 internal constant MAX_PPM = 1_000_000; error PPMMathInvalidPPM(uint256 ppm); @@ -20,10 +20,10 @@ library PPMMath { // to prevent curation fees from rounding down to zero // a must be in ppm function mulPPMRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { - if (!isValidPPM(a)) { - revert PPMMathInvalidPPM(a); + if (!isValidPPM(b)) { + revert PPMMathInvalidPPM(b); } - return b - mulPPM(MAX_PPM - a, b); + return a - mulPPM(MAX_PPM - b, a); } function isValidPPM(uint256 ppm) internal pure returns (bool) { diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 84e4fabd2..ab1bec54c 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -6,14 +6,14 @@ import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { PPMMath } from "../libraries/PPMMath.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Storage, IGraphPayments { using TokenUtils for IGraphToken; - - uint256 private immutable MAX_PPM = 1000000; // 100% in parts per million + using PPMMath for uint256; event GraphPaymentsCollected( address indexed sender, @@ -55,9 +55,9 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora _graphToken().pullTokens(msg.sender, tokens); // Calculate cuts - uint256 tokensProtocol = (tokens * PROTOCOL_PAYMENT_CUT) / MAX_PPM; + uint256 tokensProtocol = tokens.mulPPM(PROTOCOL_PAYMENT_CUT); uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, uint8(paymentType)); - uint256 tokensDelegationPool = (tokens * delegationFeeCut) / MAX_PPM; + uint256 tokensDelegationPool = tokens.mulPPM(delegationFeeCut); uint256 totalCut = tokensProtocol + tokensDataService + tokensDelegationPool; if (totalCut > tokens) { revert GraphPaymentsInsufficientTokens(tokens, totalCut); diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 6aeb5d19a..af87401c2 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -6,9 +6,10 @@ import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/Gr import { IHorizonStakingBase } from "../interfaces/IHorizonStakingBase.sol"; import { IGraphToken } from "../interfaces/IGraphToken.sol"; +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; -import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; +import { PPMMath } from "../libraries/PPMMath.sol"; import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; @@ -23,13 +24,11 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; */ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV1Storage, IHorizonStakingBase { using TokenUtils for IGraphToken; - - /// @dev 100% in parts per million - uint32 internal constant MAX_PPM = 1000000; + using PPMMath for uint256; /// @dev Maximum value that can be set as the maxVerifierCut in a provision. /// It is equivalent to 100% in parts-per-million - uint32 private constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% + uint32 private constant MAX_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); /// @dev Minimum size of a provision uint256 private constant MIN_PROVISION_SIZE = 1e18; @@ -393,7 +392,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV uint256 tokensToSlash = tokens; uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); if (providerTokensSlashed > 0) { - require((prov.tokens * prov.maxVerifierCut) / MAX_PPM >= tokensVerifier, "verifier cut too high"); + require(prov.tokens.mulPPM(prov.maxVerifierCut) >= tokensVerifier, "verifier cut too high"); if (tokensVerifier > 0) { _graphToken().pushTokens(verifierDestination, tokensVerifier); emit VerifierTokensSent(serviceProvider, verifier, verifierDestination, tokensVerifier); diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 66c088e02..7310f2d72 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -11,6 +11,7 @@ import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; import { TokenUtils } from "../libraries/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; import { ExponentialRebates } from "./libraries/ExponentialRebates.sol"; +import { PPMMath } from "../libraries/PPMMath.sol"; import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; @@ -32,9 +33,7 @@ abstract contract StakingBackwardsCompatibility is IStakingBackwardsCompatibility { using TokenUtils for IGraphToken; - - /// @dev 100% in parts per million - uint32 internal constant MAX_PPM = 1000000; + using PPMMath for uint256; address public immutable SUBGRAPH_DATA_SERVICE_ADDRESS; @@ -272,10 +271,7 @@ abstract contract StakingBackwardsCompatibility is * @return Amount of tax charged */ function _collectTax(uint256 _tokens, uint256 _percentage) private returns (uint256) { - // Calculate tokens after tax first, and subtract that, - // to prevent the tax from rounding down to zero - uint256 tokensAfterTax = ((uint256(MAX_PPM) - _percentage) * _tokens) / MAX_PPM; - uint256 tax = _tokens - tokensAfterTax; + uint256 tax = _tokens.mulPPMRoundUp(_percentage); _graphToken().burnTokens(tax); // Burn tax if any return tax; } @@ -404,8 +400,8 @@ abstract contract StakingBackwardsCompatibility is function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; - if (pool.tokens > 0 && pool.__DEPRECATED_queryFeeCut < MAX_PPM) { - uint256 indexerCut = (uint256(pool.__DEPRECATED_queryFeeCut) * _tokens) / MAX_PPM; + if (pool.tokens > 0 && uint256(pool.__DEPRECATED_queryFeeCut).isValidPPM()) { + uint256 indexerCut = uint256(pool.__DEPRECATED_queryFeeCut).mulPPM(_tokens); delegationRewards = _tokens - indexerCut; pool.tokens = pool.tokens + delegationRewards; } @@ -422,8 +418,8 @@ abstract contract StakingBackwardsCompatibility is function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; - if (pool.tokens > 0 && pool.__DEPRECATED_indexingRewardCut < MAX_PPM) { - uint256 indexerCut = (uint256(pool.__DEPRECATED_indexingRewardCut) * _tokens) / MAX_PPM; + if (pool.tokens > 0 && uint256(pool.__DEPRECATED_indexingRewardCut).isValidPPM()) { + uint256 indexerCut = uint256(pool.__DEPRECATED_indexingRewardCut).mulPPM(_tokens); delegationRewards = _tokens - indexerCut; pool.tokens = pool.tokens + delegationRewards; } @@ -451,10 +447,7 @@ abstract contract StakingBackwardsCompatibility is bool isCurationEnabled = _curationCut > 0 && address(curation) != address(0); if (isCurationEnabled && curation.isCurated(_subgraphDeploymentID)) { - // Calculate the tokens after curation fees first, and subtact that, - // to prevent curation fees from rounding down to zero - uint256 tokensAfterCurationFees = ((uint256(MAX_PPM) - _curationCut) * _tokens) / MAX_PPM; - uint256 curationFees = _tokens - tokensAfterCurationFees; + uint256 curationFees = _tokens.mulPPMRoundUp(_curationCut); if (curationFees > 0) { // Transfer and call collect() // This function transfer tokens to a trusted protocol contracts From 04432d28e080f83d4f4ad2b54acbaf6a96e6b0dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 13:40:43 -0300 Subject: [PATCH 053/277] fix: take pending rewards for subgraph service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/SubgraphService.sol | 7 ++++++- .../contracts/libraries/Allocation.sol | 11 +++++++++++ .../contracts/utilities/AllocationManager.sol | 17 +++++++++++++---- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index e82e7c7e6..dd4c92d10 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -205,7 +205,12 @@ contract SubgraphService is address allocationId ) external view override returns (address, bytes32, uint256, uint256) { Allocation.State memory allo = allocations[allocationId]; - return (allo.indexer, allo.subgraphDeploymentId, allo.tokens, allo.accRewardsPerAllocatedToken); + return ( + allo.indexer, + allo.subgraphDeploymentId, + allo.tokens, + allo.accRewardsPerAllocatedToken + allo.accRewardsPending + ); } function getLegacyAllocation(address allocationId) external view returns (LegacyAllocation.State memory) { diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index f7b5c972a..8543b4f57 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -69,6 +69,17 @@ library Allocation { return allocation; } + function clearPendingRewards( + mapping(address => State) storage self, + address allocationId + ) internal returns (State memory) { + State storage allocation = _get(self, allocationId); + if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); + allocation.accRewardsPending = 0; + + return allocation; + } + function close(mapping(address => State) storage self, address allocationId) internal returns (State memory) { State storage allocation = _get(self, allocationId); if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 62a70aee4..fa4d0a654 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -147,6 +147,9 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager ); allocations.presentPOI(allocationId); + // Any pending rewards should have been collected now + allocations.clearPendingRewards(allocationId); + if (tokensRewards == 0) { emit IndexingRewardsCollected( allocation.indexer, @@ -225,12 +228,11 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager // Update the allocation allocations[_allocationId].tokens = _tokens; allocations[_allocationId].accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; - allocations[_allocationId].accRewardsPending = allocations[_allocationId].accRewardsPending + accRewardsPending; + allocations[_allocationId].accRewardsPending += accRewardsPending; // Update total allocated tokens for the subgraph deployment - subgraphAllocatedTokens[allocation.subgraphDeploymentId] = - subgraphAllocatedTokens[allocation.subgraphDeploymentId] + - (_tokens - oldTokens); + // underflow: subgraphAllocatedTokens should at least be oldTokens so it can't underflow + subgraphAllocatedTokens[allocation.subgraphDeploymentId] += (_tokens - oldTokens); emit AllocationResized(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, _tokens, oldTokens); return allocations[_allocationId]; @@ -242,6 +244,13 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager allocations.close(_allocationId); allocationProvisionTracker.release(allocation.indexer, allocation.tokens); + // Take rewards snapshot to prevent other allos from counting tokens from this allo + allocations.snapshotRewards( + _allocationId, + _graphRewardsManager().onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) + ); + + // Update total allocated tokens for the subgraph deployment subgraphAllocatedTokens[allocation.subgraphDeploymentId] = subgraphAllocatedTokens[allocation.subgraphDeploymentId] - allocation.tokens; From 92f3a55aa92ea25416894828d87863c6fc77f1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 13:58:09 -0300 Subject: [PATCH 054/277] chore: use graph payments payment types instead of uint8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../interfaces/IHorizonStakingExtension.sol | 12 +++++++++--- .../horizon/contracts/payments/GraphPayments.sol | 2 +- .../contracts/staking/HorizonStakingExtension.sol | 11 ++++++----- .../contracts/staking/HorizonStakingStorage.sol | 5 +++-- packages/horizon/test/escrow/collect.t.sol | 2 +- packages/horizon/test/payments/GraphPayments.t.sol | 4 ++-- .../test/shared/horizon-staking/HorizonStaking.t.sol | 5 +++-- .../contracts/utilities/AllocationManager.sol | 2 +- 8 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol index 4e4811e3a..2cc79cdcb 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol @@ -4,6 +4,7 @@ pragma solidity >=0.6.12 <0.9.0; pragma abicoder v2; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; +import { IGraphPayments } from "./IGraphPayments.sol"; interface IHorizonStakingExtension is IHorizonStakingTypes { /** @@ -14,7 +15,7 @@ interface IHorizonStakingExtension is IHorizonStakingTypes { event DelegationFeeCutSet( address indexed serviceProvider, address indexed verifier, - uint256 feeType, + IGraphPayments.PaymentTypes paymentType, uint256 feeCut ); @@ -29,7 +30,12 @@ interface IHorizonStakingExtension is IHorizonStakingTypes { // for vesting contracts function setOperatorLocked(address operator, address verifier, bool allowed) external; - function setDelegationFeeCut(address serviceProvider, address verifier, uint256 feeType, uint256 feeCut) external; + function setDelegationFeeCut( + address serviceProvider, + address verifier, + IGraphPayments.PaymentTypes paymentType, + uint256 feeCut + ) external; function getStake(address serviceProvider) external view returns (uint256); @@ -60,6 +66,6 @@ interface IHorizonStakingExtension is IHorizonStakingTypes { function getDelegationFeeCut( address serviceProvider, address verifier, - uint256 feeType + IGraphPayments.PaymentTypes paymentType ) external view returns (uint256); } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index ab1bec54c..44f56d553 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -56,7 +56,7 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora // Calculate cuts uint256 tokensProtocol = tokens.mulPPM(PROTOCOL_PAYMENT_CUT); - uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, uint8(paymentType)); + uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, paymentType); uint256 tokensDelegationPool = tokens.mulPPM(delegationFeeCut); uint256 totalCut = tokensProtocol + tokensDataService + tokensDelegationPool; if (totalCut > tokens) { diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index e7b0e744d..c3e8c1675 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.24; import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; import { IHorizonStakingExtension } from "../interfaces/IHorizonStakingExtension.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; @@ -102,11 +103,11 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas function setDelegationFeeCut( address serviceProvider, address verifier, - uint256 feeType, + IGraphPayments.PaymentTypes paymentType, uint256 feeCut ) external override { - delegationFeeCut[serviceProvider][verifier][feeType] = feeCut; - emit DelegationFeeCutSet(serviceProvider, verifier, feeType, feeCut); + delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; + emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); } // total staked tokens to the provider @@ -185,9 +186,9 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas function getDelegationFeeCut( address serviceProvider, address verifier, - uint256 feeType + IGraphPayments.PaymentTypes paymentType ) external view override returns (uint256) { - return delegationFeeCut[serviceProvider][verifier][feeType]; + return delegationFeeCut[serviceProvider][verifier][paymentType]; } // provisioned tokens from delegators that are not being thawed diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index e23cde9c7..5adfa3676 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.24; import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; // TODO: create custom var-name-mixedcase /* solhint-disable var-name-mixedcase */ @@ -127,12 +128,12 @@ abstract contract HorizonStakingV1Storage { internal _provisions; /// @dev Delegation fee cuts for each service provider on each provision, by fee type: - /// ServiceProvider => Verifier => Fee Type => Fee Cut. + /// ServiceProvider => Verifier => Payment Type => Fee Cut. /// This is the effective delegator fee cuts for each (data-service-defined) fee type (e.g. indexing fees, query fees). /// This is in PPM and is the cut taken by the indexer from the fees that correspond to delegators. /// (based on stake vs delegated stake proportion). /// The cuts are applied in GraphPayments so apply to all data services that use it. - mapping(address serviceProvider => mapping(address verifier => mapping(uint256 feeType => uint256 feeCut))) + mapping(address serviceProvider => mapping(address verifier => mapping(IGraphPayments.PaymentTypes paymentType => uint256 feeCut))) public delegationFeeCut; mapping(bytes32 thawRequestId => IHorizonStakingTypes.ThawRequest thawRequest) internal _thawRequests; diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 9893d3aee..237e3230c 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -8,7 +8,7 @@ import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; contract GraphEscrowCollectTest is GraphEscrowTest { - function testCollect_Tokens(uint256 amount, uint256 tokensDataService) public useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { + function testCollect_Tokens(uint256 amount, uint256 tokensDataService) public useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 78e868cae..a584ed09d 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -12,7 +12,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { function testCollect( uint256 amount, uint256 tokensDataService - ) public useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { + ) public useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); @@ -42,7 +42,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { function testCollect_RevertWhen_InsufficientAmount( uint256 amount, uint256 tokensDataService - ) public useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { + ) public useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { vm.assume(tokensDataService <= 10_000_000_000 ether); vm.assume(tokensDataService > amount); diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol index c65032e9a..4dbddde97 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; import { GraphBaseTest } from "../../GraphBase.t.sol"; +import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol"; abstract contract HorizonStakingSharedTest is GraphBaseTest { @@ -14,7 +15,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { _; } - modifier useDelegationFeeCut(uint256 paymentType, uint256 cut) { + modifier useDelegationFeeCut(IGraphPayments.PaymentTypes paymentType, uint256 cut) { _setDelegationFeeCut(paymentType, cut); _; } @@ -41,7 +42,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { vm.stopPrank(); } - function _setDelegationFeeCut(uint256 paymentType, uint256 cut) internal { + function _setDelegationFeeCut(IGraphPayments.PaymentTypes paymentType, uint256 cut) internal { vm.prank(users.indexer); staking.setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, cut); } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index fa4d0a654..b57ef7f97 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -168,7 +168,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager uint256 delegatorCut = _graphStaking().getDelegationFeeCut( allocation.indexer, address(this), - uint8(IGraphPayments.PaymentTypes.IndexingFee) + IGraphPayments.PaymentTypes.IndexingFee ); uint256 tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); if (tokensDelegationRewards > 0) { From b95655e456c91d728f6478d0eb95511625afd4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 14:03:15 -0300 Subject: [PATCH 055/277] chore: rename indexer to service provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/IHorizonStakingBase.sol | 4 ++-- packages/horizon/contracts/staking/HorizonStaking.sol | 10 +++++----- .../contracts/staking/HorizonStakingExtension.sol | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol index 3cef3e193..0b7409a64 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol @@ -117,7 +117,7 @@ interface IHorizonStakingBase is IHorizonStakingTypes { function stakeTo(address serviceProvider, uint256 tokens) external; - // can be called by anyone if the indexer has provisioned stake to this verifier + // can be called by anyone if the service provider has provisioned stake to this verifier function stakeToProvision(address serviceProvider, address verifier, uint256 tokens) external; // create a provision @@ -186,7 +186,7 @@ interface IHorizonStakingBase is IHorizonStakingTypes { ) external; /** - * @notice Withdraw indexer tokens once the thawing period has passed. + * @notice Withdraw service provider tokens once the thawing period has passed. * @dev This is only needed during the transition period while we still have * a global lock. After that, unstake() will also withdraw. */ diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index af87401c2..9fd375e91 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -142,7 +142,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV /** * @notice Deposit tokens on the service provider stake, on behalf of the service provider, provisioned * to a specific verifier. The provider must have previously provisioned stake to that verifier. - * @param serviceProvider Address of the indexer + * @param serviceProvider Address of the service provider * @param verifier Address of the verifier * @param tokens Amount of tokens to stake */ @@ -327,7 +327,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; uint256 stakedTokens = sp.tokensStaked; - // Check that the indexer's stake minus the tokens to unstake is sufficient + // Check that the service provider's stake minus the tokens to unstake is sufficient // to cover existing allocations // TODO this is only needed until legacy allocations are closed, // so we should remove it after the transition period @@ -458,7 +458,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV } /** - * @notice Withdraw indexer tokens once the thawing period has passed. + * @notice Withdraw service provider tokens once the thawing period has passed. * @dev This is only needed during the transition period while we still have * a global lock. After that, unstake() will also withdraw. */ @@ -533,7 +533,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV /** * @notice Deposit tokens on the service provider stake, on behalf of the service provider. - * @param serviceProvider Address of the indexer + * @param serviceProvider Address of the service provider * @param tokens Amount of tokens to stake */ function stakeTo(address serviceProvider, uint256 tokens) public override notPartialPaused { @@ -831,7 +831,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV * @param _tokens Amount of tokens to stake */ function _stake(address _serviceProvider, uint256 _tokens) internal { - // Deposit tokens into the indexer stake + // Deposit tokens into the service provider stake _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; emit StakeDeposited(_serviceProvider, _tokens); diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index c3e8c1675..c73cc9de7 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -14,7 +14,7 @@ import { StakingBackwardsCompatibility } from "./StakingBackwardsCompatibility.s /** * @title L2Staking contract * @dev 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, + * to receive an service provider'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. */ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBase, IHorizonStakingExtension { @@ -68,9 +68,10 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas /** * @notice Receive tokens with a callhook from the bridge. - * @dev The encoded _data can contain information about an indexer's stake + * @dev The encoded _data can contain information about an service provider's stake * or a delegator's delegation. * See L1MessageCodes in IL2Staking for the supported messages. + * @dev "indexer" in this context refers to a service provider (legacy terminology for the bridge) * @param from Token sender in L1 * @param tokens Amount of tokens that were transferred * @param data ABI-encoded callhook data which must include a uint8 code and either a ReceiveIndexerStakeData or ReceiveDelegationData struct. From 90e5b7c31e373986e909d78a17b89c292df4c45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 14:06:22 -0300 Subject: [PATCH 056/277] chore: more indexer renames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../horizon/contracts/staking/HorizonStaking.sol | 14 +++++++------- .../contracts/staking/HorizonStakingStorage.sol | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 9fd375e91..64ab7e0c6 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -838,12 +838,12 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV } /** - * @dev Withdraw indexer tokens once the thawing period has passed. - * @param _indexer Address of indexer to withdraw funds from + * @dev Withdraw service provider tokens once the thawing period has passed. + * @param _serviceProvider Address of service provider to withdraw funds from */ - function _withdraw(address _indexer) private { + function _withdraw(address _serviceProvider) private { // Get tokens available for withdraw and update balance - ServiceProviderInternal storage sp = _serviceProviders[_indexer]; + ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; require(tokensToWithdraw > 0, "!tokens"); require(block.number >= sp.__DEPRECATED_tokensLockedUntil, "locked"); @@ -854,9 +854,9 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; - // Return tokens to the indexer - _graphToken().pushTokens(_indexer, tokensToWithdraw); + // Return tokens to the service provider + _graphToken().pushTokens(_serviceProvider, tokensToWithdraw); - emit StakeWithdrawn(_indexer, tokensToWithdraw); + emit StakeWithdrawn(_serviceProvider, tokensToWithdraw); } } diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 5adfa3676..5c85f910b 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -98,7 +98,7 @@ abstract contract HorizonStakingV1Storage { // -- Operators -- - /// @dev Legacy operator auth : indexer => operator => is authorized + /// @dev Legacy operator auth : service provider => operator => is authorized mapping(address legacyOperator => mapping(address serviceProvider => bool authorized)) internal _legacyOperatorAuth; // -- Asset Holders -- @@ -130,7 +130,7 @@ abstract contract HorizonStakingV1Storage { /// @dev Delegation fee cuts for each service provider on each provision, by fee type: /// ServiceProvider => Verifier => Payment Type => Fee Cut. /// This is the effective delegator fee cuts for each (data-service-defined) fee type (e.g. indexing fees, query fees). - /// This is in PPM and is the cut taken by the indexer from the fees that correspond to delegators. + /// This is in PPM and is the cut taken by the service provider from the fees that correspond to delegators. /// (based on stake vs delegated stake proportion). /// The cuts are applied in GraphPayments so apply to all data services that use it. mapping(address serviceProvider => mapping(address verifier => mapping(IGraphPayments.PaymentTypes paymentType => uint256 feeCut))) @@ -138,7 +138,7 @@ abstract contract HorizonStakingV1Storage { mapping(bytes32 thawRequestId => IHorizonStakingTypes.ThawRequest thawRequest) internal _thawRequests; - // indexer => verifier => operator => authorized + // service provider => verifier => operator => authorized mapping(address serviceProvider => mapping(address verifier => mapping(address operator => bool authorized))) internal _operatorAuth; From b2207616d843ac4e741a0606e8e00b8709d9b40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 14:08:50 -0300 Subject: [PATCH 057/277] chore: remove unnecessary pragma abicoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2 is default since 0.8.0 Signed-off-by: Tomás Migone --- packages/subgraph-service/contracts/DisputeManager.sol | 1 - .../subgraph-service/contracts/interfaces/IDisputeManager.sol | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 69190b27f..12395625e 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.24; -pragma abicoder v2; import { IGraphToken } from "@graphprotocol/horizon/contracts/interfaces/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 70fe4e7f8..e9880944d 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.24; -pragma abicoder v2; import { Attestation } from "../libraries/Attestation.sol"; From 444233591ebcf10f436f5e21f6388274e079208a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 14:54:00 -0300 Subject: [PATCH 058/277] chore: update solidity version, remove duplicate files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/contracts/base/IMulticall.sol | 2 +- .../contracts/contracts/base/Multicall.sol | 2 +- .../contracts/curation/ICuration.sol | 2 +- .../contracts/epochs/IEpochManager.sol | 2 +- .../contracts/gateway/ICallhookReceiver.sol | 2 +- .../contracts/governance/Controller.sol | 2 +- .../contracts/governance/Governed.sol | 2 +- .../contracts/governance/IController.sol | 2 +- .../contracts/governance/IManaged.sol | 2 +- .../contracts/governance/Managed.sol | 2 +- .../contracts/governance/Pausable.sol | 2 +- .../contracts/l2/staking/IL2StakingBase.sol | 2 +- .../contracts/l2/staking/IL2StakingTypes.sol | 2 +- .../contracts/rewards/IRewardsIssuer.sol | 2 +- .../contracts/rewards/IRewardsManager.sol | 2 +- .../contracts/staking/IHorizonStaking.sol | 166 ------------------ .../contracts/contracts/token/IGraphToken.sol | 2 +- .../contracts/upgrades/GraphProxy.sol | 2 +- .../contracts/upgrades/GraphProxyAdmin.sol | 2 +- .../contracts/upgrades/GraphProxyStorage.sol | 2 +- .../contracts/upgrades/IGraphProxy.sol | 2 +- .../contracts/contracts/utils/TokenUtils.sol | 8 +- .../contracts/data-service/GraphDirectory.sol | 2 +- .../contracts/interfaces/IGraphToken.sol | 43 ----- .../contracts/interfaces/IHorizonStaking.sol | 3 +- .../interfaces/IHorizonStakingBase.sol | 3 +- .../interfaces/IHorizonStakingExtension.sol | 3 +- .../interfaces/IHorizonStakingTypes.sol | 3 +- .../IStakingBackwardsCompatibility.sol | 3 +- .../contracts/libraries/TokenUtils.sol | 48 ----- .../contracts/payments/GraphPayments.sol | 4 +- .../contracts/payments/PaymentsEscrow.sol | 4 +- .../contracts/staking/HorizonStaking.sol | 4 +- .../staking/StakingBackwardsCompatibility.sol | 4 +- .../contracts/DisputeManager.sol | 4 +- 35 files changed, 43 insertions(+), 299 deletions(-) delete mode 100644 packages/contracts/contracts/staking/IHorizonStaking.sol delete mode 100644 packages/horizon/contracts/interfaces/IGraphToken.sol delete mode 100644 packages/horizon/contracts/libraries/TokenUtils.sol diff --git a/packages/contracts/contracts/base/IMulticall.sol b/packages/contracts/contracts/base/IMulticall.sol index 65d69d24e..3269f694b 100644 --- a/packages/contracts/contracts/base/IMulticall.sol +++ b/packages/contracts/contracts/base/IMulticall.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6; pragma abicoder v2; /** diff --git a/packages/contracts/contracts/base/Multicall.sol b/packages/contracts/contracts/base/Multicall.sol index eff2d3e28..49111840d 100644 --- a/packages/contracts/contracts/base/Multicall.sol +++ b/packages/contracts/contracts/base/Multicall.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6; pragma abicoder v2; import "./IMulticall.sol"; diff --git a/packages/contracts/contracts/curation/ICuration.sol b/packages/contracts/contracts/curation/ICuration.sol index 27d37f38c..b57efaf2a 100644 --- a/packages/contracts/contracts/curation/ICuration.sol +++ b/packages/contracts/contracts/curation/ICuration.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; /** * @title Curation Interface diff --git a/packages/contracts/contracts/epochs/IEpochManager.sol b/packages/contracts/contracts/epochs/IEpochManager.sol index f9a365b9c..5f02e3579 100644 --- a/packages/contracts/contracts/epochs/IEpochManager.sol +++ b/packages/contracts/contracts/epochs/IEpochManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; interface IEpochManager { // -- Configuration -- diff --git a/packages/contracts/contracts/gateway/ICallhookReceiver.sol b/packages/contracts/contracts/gateway/ICallhookReceiver.sol index 33b06ab5e..e869c7f4e 100644 --- a/packages/contracts/contracts/gateway/ICallhookReceiver.sol +++ b/packages/contracts/contracts/gateway/ICallhookReceiver.sol @@ -6,7 +6,7 @@ * 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.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; interface ICallhookReceiver { /** diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index 74854cbfe..9c369b0b7 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.7.6 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; import { IController } from "./IController.sol"; import { IManaged } from "./IManaged.sol"; diff --git a/packages/contracts/contracts/governance/Governed.sol b/packages/contracts/contracts/governance/Governed.sol index 570e2839c..0d1c1250b 100644 --- a/packages/contracts/contracts/governance/Governed.sol +++ b/packages/contracts/contracts/governance/Governed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.7.6 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; /** * @title Graph Governance contract diff --git a/packages/contracts/contracts/governance/IController.sol b/packages/contracts/contracts/governance/IController.sol index 0549c723d..634c881d3 100644 --- a/packages/contracts/contracts/governance/IController.sol +++ b/packages/contracts/contracts/governance/IController.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; interface IController { function getGovernor() external view returns (address); diff --git a/packages/contracts/contracts/governance/IManaged.sol b/packages/contracts/contracts/governance/IManaged.sol index 4cedf9c0b..5ef387b5d 100644 --- a/packages/contracts/contracts/governance/IManaged.sol +++ b/packages/contracts/contracts/governance/IManaged.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; import { IController } from "./IController.sol"; diff --git a/packages/contracts/contracts/governance/Managed.sol b/packages/contracts/contracts/governance/Managed.sol index f0172dc94..fb65e71b9 100644 --- a/packages/contracts/contracts/governance/Managed.sol +++ b/packages/contracts/contracts/governance/Managed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6; import { IController } from "./IController.sol"; diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 1e9baf5fe..9ebf36a1c 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.7.6 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; abstract contract Pausable { /** diff --git a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol index 3926dd708..9ae4b850b 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; diff --git a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol index 41d3fe445..2bc452a4a 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; interface IL2StakingTypes { /// @dev Message codes for the L1 -> L2 bridge callhook diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol index bf2f8c430..67588aee3 100644 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; interface IRewardsIssuer { /** diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index 2d2bd4003..5c4de5461 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; interface IRewardsManager { /** diff --git a/packages/contracts/contracts/staking/IHorizonStaking.sol b/packages/contracts/contracts/staking/IHorizonStaking.sol deleted file mode 100644 index b45aee1ac..000000000 --- a/packages/contracts/contracts/staking/IHorizonStaking.sol +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity >=0.7.6 <0.9.0; -pragma abicoder v2; - -interface Test { - function test() external returns (uint256); -} - -interface IHorizonStaking { - struct Provision { - // Service provider that created the provision - address serviceProvider; - // tokens in the provision - uint256 tokens; - // delegated tokens in the provision - uint256 delegatedTokens; - // tokens that are being thawed (and will stop being slashable soon) - uint256 tokensThawing; - // timestamp of provision creation - uint64 createdAt; - // authority to slash the provision - address verifier; - // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed - uint32 maxVerifierCut; - // time, in seconds, tokens must thaw before being withdrawn - uint64 thawingPeriod; - } - - // the new "Indexer" struct - struct ServiceProviderInternal { - // Tokens on the Service Provider stake (staked by the provider) - uint256 tokensStaked; - // Tokens used in allocations - uint256 __DEPRECATED_tokensAllocated; - // Tokens locked for withdrawal subject to thawing period - uint256 __DEPRECATED_tokensLocked; - // Block when locked tokens can be withdrawn - uint256 __DEPRECATED_tokensLockedUntil; - // tokens used in a provision - uint256 tokensProvisioned; - // tokens that initiated a thawing in any one of the provider's provisions - uint256 tokensRequestedThaw; - // tokens that have been removed from any one of the provider's provisions after thawing - uint256 tokensFulfilledThaw; - // provisions that take priority for undelegation force thawing - bytes32[] forceThawProvisions; - } - - struct ServiceProvider { - // Tokens on the provider stake (staked by the provider) - uint256 tokensStaked; - // tokens used in a provision - uint256 tokensProvisioned; - // tokens that initiated a thawing in any one of the provider's provisions - uint256 tokensRequestedThaw; - // tokens that have been removed from any one of the provider's provisions after thawing - uint256 tokensFulfilledThaw; - // provisions that take priority for undelegation force thawing - bytes32[] forceThawProvisions; - } - - struct DelegationPool { - uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase - uint32 __DEPRECATED_indexingRewardCut; // in PPM - uint32 __DEPRECATED_queryFeeCut; // in PPM - uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated - uint256 tokens; // Total tokens as pool reserves - uint256 shares; // Total shares minted in the pool - mapping(address => Delegation) delegators; // Mapping of delegator => Delegation - } - - struct Delegation { - // shares owned by the delegator in the pool - uint256 shares; - // tokens delegated to the pool - uint256 tokens; - // Timestamp when locked tokens can be undelegated (after the timelock) - uint256 tokensLockedUntil; - } - - struct ThawRequest { - // tokens that are being thawed by this request - uint256 tokens; - // the provision id to which this request corresponds to - bytes32 provisionId; - // the address that initiated the thaw request, allowed to remove the funds once thawed - address owner; - // the timestamp when the thawed funds can be removed from the provision - uint64 thawingUntil; - // the value of `ServiceProvider.tokensRequestedThaw` the moment the thaw request is created - uint256 tokensRequestedThawSnapshot; - } - - // whitelist/deny a verifier - function allowVerifier(address verifier, bool allow) external; - - // deposit stake - function stake(uint256 tokens) external; - - // create a provision - function provision(uint256 tokens, address verifier, uint32 maxVerifierCut, uint64 thawingPeriod) external; - - // accept a provision - function acceptProvision(address serviceProvider) external; - - // initiate a thawing to remove tokens from a provision - function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId); - - // moves thawed stake from a provision back into the provider's available stake - function deprovision(bytes32 thawRequestId) external; - - // moves thawed stake from one provision into another provision - function reprovision(bytes32 thawRequestId, bytes32 provisionId) external; - - // moves thawed stake back to the owner's account - stake is removed from the protocol - function withdraw(bytes32 thawRequestId) external; - - // delegate tokens to a provider - function delegate(address serviceProvider, uint256 tokens) external; - - // undelegate tokens - function undelegate( - address serviceProvider, - uint256 tokens, - bytes32[] calldata provisions - ) external returns (bytes32 thawRequestId); - - // slash a service provider - function slash(address serviceProvider, uint256 tokens, uint256 reward, address rewardsDestination) external; - - // set the Service Provider's preferred provisions to be force thawed - function setForceThawProvisions(bytes32[] calldata provisions) external; - - // total staked tokens to the provider - // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` - function getStake(address serviceProvider) external view returns (uint256 tokens); - - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) external view returns (uint256 tokens); - - // staked tokens the provider can provision before hitting the delegation cap - // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` - function getCapacity(address serviceProvider) external view returns (uint256 tokens); - - // provisioned tokens that are not being used - // `Provision.tokens - Provision.tokensThawing` - function getTokensAvailable(address serviceProvider, address verifier) external view returns (uint256 tokens); - - function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); - - function getProvision(address serviceProvider, address verifier) external view returns (Provision memory); - - /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param _operator The address to check for auth - * @param _serviceProvider The service provider on behalf of whom they're claiming to act - * @param _verifier The verifier / data service on which they're claiming to act - */ - function isAuthorized(address _operator, address _serviceProvider, address _verifier) external view returns (bool); - - function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256 delegationCut); - function addToDelegationPool(address serviceProvider, uint256 tokens) external; - function stakeToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external; -} diff --git a/packages/contracts/contracts/token/IGraphToken.sol b/packages/contracts/contracts/token/IGraphToken.sol index f24467d42..1342625df 100644 --- a/packages/contracts/contracts/token/IGraphToken.sol +++ b/packages/contracts/contracts/token/IGraphToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.7.6 <=0.9.0; +pragma solidity ^0.7.6 || 0.8.24; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxy.sol b/packages/contracts/contracts/upgrades/GraphProxy.sol index c5c01ca8f..a95428f68 100644 --- a/packages/contracts/contracts/upgrades/GraphProxy.sol +++ b/packages/contracts/contracts/upgrades/GraphProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; import { GraphProxyStorage } from "./GraphProxyStorage.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol index 8fb735901..0d3b075a5 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; import { Governed } from "../governance/Governed.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol index 42e2a0545..9117ff54d 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; /** * @title Graph Proxy Storage diff --git a/packages/contracts/contracts/upgrades/IGraphProxy.sol b/packages/contracts/contracts/upgrades/IGraphProxy.sol index cee1aadb0..59d4a323d 100644 --- a/packages/contracts/contracts/upgrades/IGraphProxy.sol +++ b/packages/contracts/contracts/upgrades/IGraphProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; +pragma solidity ^0.7.6 || 0.8.24; interface IGraphProxy { function admin() external returns (address); diff --git a/packages/contracts/contracts/utils/TokenUtils.sol b/packages/contracts/contracts/utils/TokenUtils.sol index 09d9ed704..f33bc5c85 100644 --- a/packages/contracts/contracts/utils/TokenUtils.sol +++ b/packages/contracts/contracts/utils/TokenUtils.sol @@ -1,9 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.7.6 <=0.8.24; +pragma solidity ^0.7.6 || 0.8.24; import "../token/IGraphToken.sol"; +/** + * @title TokenUtils library + * @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. diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index 3f50440b2..ae9f9cdaf 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; -import { IGraphToken } from "../interfaces/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; diff --git a/packages/horizon/contracts/interfaces/IGraphToken.sol b/packages/horizon/contracts/interfaces/IGraphToken.sol deleted file mode 100644 index cb0b6cae6..000000000 --- a/packages/horizon/contracts/interfaces/IGraphToken.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity 0.8.24; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -interface IGraphToken is IERC20 { - // -- Mint and Burn -- - - function burn(uint256 tokens) external; - - function burnFrom(address from, uint256 tokens) external; - - function mint(address to, uint256 tokens) external; - - // -- Mint Admin -- - - function addMinter(address account) external; - - function removeMinter(address account) external; - - function renounceMinter() external; - - // -- Permit -- - - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - // -- Allowance -- - - function increaseAllowance(address spender, uint256 addedValue) external returns (bool); - - function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); - - function isMinter(address account) external view returns (bool); -} diff --git a/packages/horizon/contracts/interfaces/IHorizonStaking.sol b/packages/horizon/contracts/interfaces/IHorizonStaking.sol index 2c9dab033..297ccdcbe 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStaking.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStaking.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; -pragma abicoder v2; +pragma solidity 0.8.24; import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; import { IHorizonStakingExtension } from "./IHorizonStakingExtension.sol"; diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol index 0b7409a64..9a7c480dc 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; -pragma abicoder v2; +pragma solidity 0.8.24; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol index 2cc79cdcb..99ff66677 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; -pragma abicoder v2; +pragma solidity 0.8.24; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; import { IGraphPayments } from "./IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol index f737d52ee..f95fff4c4 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; -pragma abicoder v2; +pragma solidity 0.8.24; // TODO: create custom var-name-mixedcase /* solhint-disable var-name-mixedcase */ diff --git a/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol b/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol index 088ee3776..bf5efbf0d 100644 --- a/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.6.12 <0.9.0; -pragma abicoder v2; +pragma solidity 0.8.24; /** * @title Base interface for the Staking contract. diff --git a/packages/horizon/contracts/libraries/TokenUtils.sol b/packages/horizon/contracts/libraries/TokenUtils.sol deleted file mode 100644 index 30903d6ae..000000000 --- a/packages/horizon/contracts/libraries/TokenUtils.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity 0.8.24; - -import { IGraphToken } from "../interfaces/IGraphToken.sol"; - -/** - * @title TokenUtils library - * @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. - * @param _graphToken Token to transfer - * @param _from Address sending the tokens - * @param _tokens Amount of tokens to transfer - */ - function pullTokens(IGraphToken _graphToken, address _from, uint256 _tokens) internal { - if (_tokens > 0) { - require(_graphToken.transferFrom(_from, address(this), _tokens), "!transfer"); - } - } - - /** - * @dev Push tokens from this contract to a receiving address. - * @param _graphToken Token to transfer - * @param _to Address receiving the tokens - * @param _tokens Amount of tokens to transfer - */ - function pushTokens(IGraphToken _graphToken, address _to, uint256 _tokens) internal { - if (_tokens > 0) { - require(_graphToken.transfer(_to, _tokens), "!transfer"); - } - } - - /** - * @dev Burn tokens held by this contract. - * @param _graphToken Token to burn - * @param _tokens Amount of tokens to burn - */ - function burnTokens(IGraphToken _graphToken, uint256 _tokens) internal { - if (_tokens > 0) { - _graphToken.burn(_tokens); - } - } -} diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 44f56d553..2cf88e058 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphToken } from "../interfaces/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; -import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 6d7e82d11..90e69ae5f 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import { IGraphToken } from "../interfaces/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; -import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 64ab7e0c6..73707f623 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -3,11 +3,11 @@ pragma solidity 0.8.24; import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingBase } from "../interfaces/IHorizonStakingBase.sol"; -import { IGraphToken } from "../interfaces/IGraphToken.sol"; import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; -import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol index 7310f2d72..b0b46a9a5 100644 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol @@ -4,11 +4,11 @@ pragma solidity 0.8.24; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; -import { IGraphToken } from "../interfaces/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; -import { TokenUtils } from "../libraries/TokenUtils.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; import { ExponentialRebates } from "./libraries/ExponentialRebates.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 12395625e..1e6f1452e 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.24; -import { IGraphToken } from "@graphprotocol/horizon/contracts/interfaces/IGraphToken.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; -import { TokenUtils } from "@graphprotocol/horizon/contracts/libraries/TokenUtils.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { Allocation } from "./libraries/Allocation.sol"; import { Attestation } from "./libraries/Attestation.sol"; From f4802b22c636efcf6f181935a750a70ecfb7b827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 23 May 2024 15:57:33 -0300 Subject: [PATCH 059/277] chore: pin solidity version to 0.8.24 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/contracts/data-service/DataService.sol | 2 +- .../horizon/contracts/data-service/DataServiceStorage.sol | 2 +- packages/horizon/contracts/data-service/GraphDirectory.sol | 4 ++-- .../contracts/data-service/extensions/DataServiceFees.sol | 2 +- .../data-service/extensions/DataServiceFeesStorage.sol | 2 +- .../data-service/extensions/DataServicePausable.sol | 2 +- .../data-service/extensions/DataServiceRescuable.sol | 2 +- .../contracts/data-service/extensions/IDataServiceFees.sol | 2 +- .../data-service/extensions/IDataServicePausable.sol | 2 +- .../data-service/extensions/IDataServiceRescuable.sol | 2 +- .../contracts/data-service/libraries/ProvisionGetter.sol | 2 +- .../contracts/data-service/libraries/ProvisionTracker.sol | 2 +- .../contracts/data-service/utilities/ProvisionManager.sol | 2 +- .../data-service/utilities/ProvisionManagerStorage.sol | 2 +- .../contracts/interfaces}/IBridgeEscrow.sol | 6 +++--- packages/horizon/contracts/interfaces/IDataService.sol | 2 +- packages/horizon/contracts/interfaces/IGraphPayments.sol | 2 +- .../contracts/interfaces}/IGraphProxyAdmin.sol | 0 packages/horizon/contracts/interfaces/IPaymentsEscrow.sol | 2 +- packages/horizon/contracts/interfaces/ITAPCollector.sol | 2 +- packages/horizon/contracts/libraries/Denominations.sol | 2 +- packages/horizon/contracts/libraries/PPMMath.sol | 2 +- packages/horizon/contracts/libraries/UintRange.sol | 2 +- packages/horizon/contracts/mocks/MockGRTToken.sol | 2 +- packages/horizon/contracts/payments/GraphPayments.sol | 2 +- .../horizon/contracts/payments/GraphPaymentsStorage.sol | 2 +- packages/horizon/contracts/payments/PaymentsEscrow.sol | 2 +- .../horizon/contracts/payments/collectors/TAPCollector.sol | 2 +- packages/horizon/test/GraphBase.t.sol | 2 +- packages/horizon/test/deployments/Deployments.t.sol | 2 +- packages/horizon/test/escrow/GraphEscrow.t.sol | 2 +- packages/horizon/test/escrow/collect.t.sol | 2 +- packages/horizon/test/escrow/collector.t.sol | 2 +- packages/horizon/test/escrow/deposit.t.sol | 2 +- packages/horizon/test/escrow/thaw.t.sol | 2 +- packages/horizon/test/escrow/withdraw.t.sol | 2 +- packages/horizon/test/payments/GraphPayments.t.sol | 2 +- .../test/shared/horizon-staking/HorizonStaking.t.sol | 2 +- packages/horizon/test/utils/Constants.sol | 2 +- packages/horizon/test/utils/Users.sol | 2 +- packages/subgraph-service/contracts/DisputeManager.sol | 2 +- .../subgraph-service/contracts/DisputeManagerStorage.sol | 2 +- packages/subgraph-service/contracts/SubgraphService.sol | 2 +- .../subgraph-service/contracts/SubgraphServiceStorage.sol | 2 +- .../contracts/interfaces/IDisputeManager.sol | 2 +- .../contracts/interfaces/ISubgraphService.sol | 2 +- .../subgraph-service/contracts/libraries/Allocation.sol | 2 +- .../subgraph-service/contracts/libraries/Attestation.sol | 2 +- .../contracts/libraries/LegacyAllocation.sol | 2 +- .../contracts/utilities/AllocationManager.sol | 2 +- .../contracts/utilities/AllocationManagerStorage.sol | 2 +- .../contracts/utilities/AttestationManager.sol | 2 +- .../contracts/utilities/AttestationManagerStorage.sol | 2 +- packages/subgraph-service/contracts/utilities/Directory.sol | 2 +- packages/subgraph-service/test/DisputeManager.t.sol | 2 +- packages/subgraph-service/test/mocks/MockGRTToken.sol | 2 +- packages/subgraph-service/test/mocks/MockHorizonStaking.sol | 2 +- packages/subgraph-service/test/mocks/MockRewardsManager.sol | 2 +- 58 files changed, 60 insertions(+), 60 deletions(-) rename packages/{contracts/contracts/gateway => horizon/contracts/interfaces}/IBridgeEscrow.sol (80%) rename packages/{contracts/contracts/upgrades => horizon/contracts/interfaces}/IGraphProxyAdmin.sol (100%) diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index 06c484aa2..79e62216f 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataService } from "../interfaces/IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/DataServiceStorage.sol b/packages/horizon/contracts/data-service/DataServiceStorage.sol index 3cb7e0b86..92e73e690 100644 --- a/packages/horizon/contracts/data-service/DataServiceStorage.sol +++ b/packages/horizon/contracts/data-service/DataServiceStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; abstract contract DataServiceV1Storage { /// @dev Gap to allow adding variables in future upgrades diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index ae9f9cdaf..6171e06c8 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -11,8 +11,8 @@ import { IController } from "@graphprotocol/contracts/contracts/governance/ICont import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; import { ITokenGateway } from "@graphprotocol/contracts/contracts/arbitrum/ITokenGateway.sol"; -import { IBridgeEscrow } from "@graphprotocol/contracts/contracts/gateway/IBridgeEscrow.sol"; -import { IGraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/IGraphProxyAdmin.sol"; +import { IBridgeEscrow } from "../interfaces/IBridgeEscrow.sol"; +import { IGraphProxyAdmin } from "../interfaces/IGraphProxyAdmin.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 2ea9ffe2c..b61526cf7 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataServiceFees } from "./IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 4296a952a..a55a393e3 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataServiceFees } from "./IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index ab0ec97c3..dc35d5f8a 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataServicePausable } from "./IDataServicePausable.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 45a1cd4f9..fd790dae3 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IDataServiceRescuable } from "./IDataServiceRescuable.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol index fe75755fe..58f9f876f 100644 --- a/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataService } from "../../interfaces/IDataService.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol index 302e8a67e..6996c2bcf 100644 --- a/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataService } from "../../interfaces/IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol index 18eee452d..e8075dab5 100644 --- a/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataService } from "../../interfaces/IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol b/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol index 6fdf1e2c4..f0ef2d382 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index f0acc7f89..cc86b71e3 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 54a24b9bc..f13adecf8 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index 2f129adef..6e62d134c 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; abstract contract ProvisionManagerV1Storage { /// @notice The minimum amount of tokens required to register a provision in the data service diff --git a/packages/contracts/contracts/gateway/IBridgeEscrow.sol b/packages/horizon/contracts/interfaces/IBridgeEscrow.sol similarity index 80% rename from packages/contracts/contracts/gateway/IBridgeEscrow.sol rename to packages/horizon/contracts/interfaces/IBridgeEscrow.sol index 733288e9c..372f8ba0c 100644 --- a/packages/contracts/contracts/gateway/IBridgeEscrow.sol +++ b/packages/horizon/contracts/interfaces/IBridgeEscrow.sol @@ -10,17 +10,17 @@ interface IBridgeEscrow { * @notice Initialize the BridgeEscrow contract. * @param _controller Address of the Controller that manages this contract */ - function initialize(address _controller) external; + function initialize(address ontroller) external; /** * @notice Approve a spender (i.e. a bridge that manages the GRT funds held by the escrow) * @param _spender Address of the spender that will be approved */ - function approveAll(address _spender) external; + function approveAll(address sender) external; /** * @notice Revoke a spender (i.e. a bridge that will no longer manage the GRT funds held by the escrow) * @param _spender Address of the spender that will be revoked */ - function revokeAll(address _spender) external; + function revokeAll(address spnder) external; } diff --git a/packages/horizon/contracts/interfaces/IDataService.sol b/packages/horizon/contracts/interfaces/IDataService.sol index e6ca8fabe..7b401e533 100644 --- a/packages/horizon/contracts/interfaces/IDataService.sol +++ b/packages/horizon/contracts/interfaces/IDataService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphPayments } from "./IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index acad67e99..bb0274b2d 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; interface IGraphPayments { // Payment types diff --git a/packages/contracts/contracts/upgrades/IGraphProxyAdmin.sol b/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol similarity index 100% rename from packages/contracts/contracts/upgrades/IGraphProxyAdmin.sol rename to packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index de3f0af06..20b10491f 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphPayments } from "./IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 217f7a1a6..90b2c53dd 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IPaymentsCollector } from "./IPaymentsCollector.sol"; diff --git a/packages/horizon/contracts/libraries/Denominations.sol b/packages/horizon/contracts/libraries/Denominations.sol index a5f543fb2..201051447 100644 --- a/packages/horizon/contracts/libraries/Denominations.sol +++ b/packages/horizon/contracts/libraries/Denominations.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; /** * @title Denominations diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index 2129f4a96..3eb3a5b69 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; library PPMMath { /// @notice Maximum value (100%) in parts per million (PPM). diff --git a/packages/horizon/contracts/libraries/UintRange.sol b/packages/horizon/contracts/libraries/UintRange.sol index f98714d25..d8265e35f 100644 --- a/packages/horizon/contracts/libraries/UintRange.sol +++ b/packages/horizon/contracts/libraries/UintRange.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; library UintRange { using UintRange for uint256; diff --git a/packages/horizon/contracts/mocks/MockGRTToken.sol b/packages/horizon/contracts/mocks/MockGRTToken.sol index 7d7e1cc9e..af50cbdfd 100644 --- a/packages/horizon/contracts/mocks/MockGRTToken.sol +++ b/packages/horizon/contracts/mocks/MockGRTToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 2cf88e058..bab59365d 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol index 09a8691d8..f05499249 100644 --- a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol +++ b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; contract GraphPaymentsStorageV1Storage { // The graph protocol payment cut diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 90e69ae5f..fd30bd758 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index 1a0a66ab7..94f601ad5 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; import { ITAPCollector } from "../../interfaces/ITAPCollector.sol"; diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 3055c9245..b45797fdf 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/deployments/Deployments.t.sol b/packages/horizon/test/deployments/Deployments.t.sol index 3af5e027c..2832bc69b 100644 --- a/packages/horizon/test/deployments/Deployments.t.sol +++ b/packages/horizon/test/deployments/Deployments.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index fffa82830..c4041be16 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 237e3230c..7317f9c0e 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index 9274f6f9d..1e3fd3fb8 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol index 8a83043e2..05c6d557d 100644 --- a/packages/horizon/test/escrow/deposit.t.sol +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 287400d8f..72a1fc176 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index be47fea83..6d70b64f7 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index a584ed09d..655700c6a 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol index 4dbddde97..464665d51 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index ff7f77dfb..44ed15fdf 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; abstract contract Constants { uint256 internal constant MAX_PPM = 1000000; // 100% in parts per million diff --git a/packages/horizon/test/utils/Users.sol b/packages/horizon/test/utils/Users.sol index 39f1a2a5f..a834e18a9 100644 --- a/packages/horizon/test/utils/Users.sol +++ b/packages/horizon/test/utils/Users.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; struct Users { address governor; diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 1e6f1452e..9eda3f42d 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol index e3af4bf53..c90ef885d 100644 --- a/packages/subgraph-service/contracts/DisputeManagerStorage.sol +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index dd4c92d10..b252346a5 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 671279989..3904b7ba4 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index e9880944d..8c3df586d 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { Attestation } from "../libraries/Attestation.sol"; diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index e1f85ec25..52561fb74 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/extensions/IDataServiceFees.sol"; diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index 8543b4f57..5d7dd4f82 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; library Allocation { using Allocation for State; diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index 1ff99b0e3..de85d9ca0 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; library Attestation { // Receipt content sent from the service provider in response to request diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol index bef060e8b..18b5bdb1e 100644 --- a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; library LegacyAllocation { using LegacyAllocation for State; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index b57ef7f97..4423473ea 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol index c737acabf..525c83b54 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index 2c1e18150..54b538c89 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { AttestationManagerV1Storage } from "./AttestationManagerStorage.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol index 80aa0388f..2841334ff 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; abstract contract AttestationManagerV1Storage { bytes32 internal _domainSeparator; diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index f4e756cf6..ca7a45a73 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import { IDisputeManager } from "../interfaces/IDisputeManager.sol"; import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol index fea4d3ed7..64838c6bb 100644 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/mocks/MockGRTToken.sol b/packages/subgraph-service/test/mocks/MockGRTToken.sol index 11cf5c0f8..cab52fb35 100644 --- a/packages/subgraph-service/test/mocks/MockGRTToken.sol +++ b/packages/subgraph-service/test/mocks/MockGRTToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index 7b21f25a1..13281fa6e 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index f2447c7c4..c98b60ca7 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import "forge-std/Test.sol"; From a390aea68fce24002633bc3f1f2f62aa1010a495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 12:24:59 -0300 Subject: [PATCH 060/277] Tmigone/horizon staking revamp (#973) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: typos Signed-off-by: Tomás Migone * chore: refactor HorizonStaking Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone --- .../contracts/interfaces/IBridgeEscrow.sol | 12 +- .../contracts/interfaces/IHorizonStaking.sol | 5 +- .../interfaces/IHorizonStakingBase.sol | 228 ++----- .../interfaces/IHorizonStakingExtension.sol | 188 ++++-- .../interfaces/IHorizonStakingMain.sol | 252 ++++++++ .../IStakingBackwardsCompatibility.sol | 189 ------ .../contracts/staking/HorizonStaking.sol | 149 ++--- .../contracts/staking/HorizonStakingBase.sol | 200 +++++++ .../staking/HorizonStakingExtension.sol | 558 ++++++++++++++---- .../staking/HorizonStakingStorage.sol | 5 +- .../staking/StakingBackwardsCompatibility.sol | 482 --------------- packages/horizon/hardhat.config.ts | 1 + packages/horizon/package.json | 1 + yarn.lock | 1 + 14 files changed, 1121 insertions(+), 1150 deletions(-) create mode 100644 packages/horizon/contracts/interfaces/IHorizonStakingMain.sol delete mode 100644 packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol create mode 100644 packages/horizon/contracts/staking/HorizonStakingBase.sol delete mode 100644 packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol diff --git a/packages/horizon/contracts/interfaces/IBridgeEscrow.sol b/packages/horizon/contracts/interfaces/IBridgeEscrow.sol index 372f8ba0c..19a13a0f2 100644 --- a/packages/horizon/contracts/interfaces/IBridgeEscrow.sol +++ b/packages/horizon/contracts/interfaces/IBridgeEscrow.sol @@ -8,19 +8,19 @@ pragma solidity 0.8.24; interface IBridgeEscrow { /** * @notice Initialize the BridgeEscrow contract. - * @param _controller Address of the Controller that manages this contract + * @param controller Address of the Controller that manages this contract */ - function initialize(address ontroller) external; + function initialize(address controller) external; /** * @notice Approve a spender (i.e. a bridge that manages the GRT funds held by the escrow) - * @param _spender Address of the spender that will be approved + * @param spender Address of the spender that will be approved */ - function approveAll(address sender) external; + function approveAll(address spender) external; /** * @notice Revoke a spender (i.e. a bridge that will no longer manage the GRT funds held by the escrow) - * @param _spender Address of the spender that will be revoked + * @param spender Address of the spender that will be revoked */ - function revokeAll(address spnder) external; + function revokeAll(address spender) external; } diff --git a/packages/horizon/contracts/interfaces/IHorizonStaking.sol b/packages/horizon/contracts/interfaces/IHorizonStaking.sol index 297ccdcbe..96560f7a3 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStaking.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStaking.sol @@ -2,7 +2,8 @@ pragma solidity 0.8.24; -import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; +import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; +import { IHorizonStakingMain } from "./IHorizonStakingMain.sol"; import { IHorizonStakingExtension } from "./IHorizonStakingExtension.sol"; -interface IHorizonStaking is IHorizonStakingBase, IHorizonStakingExtension {} +interface IHorizonStaking is IHorizonStakingTypes, IHorizonStakingMain, IHorizonStakingExtension {} diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol index 9a7c480dc..a5f6e4fa4 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol @@ -3,229 +3,67 @@ pragma solidity 0.8.24; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; +import { IGraphPayments } from "./IGraphPayments.sol"; -interface IHorizonStakingBase is IHorizonStakingTypes { +interface IHorizonStakingBase { /** * @dev Emitted when `serviceProvider` stakes `tokens` amount. + * @dev TODO(after transition period): move to IHorizonStakingMain */ event StakeDeposited(address indexed serviceProvider, uint256 tokens); /** - * @dev Emitted when `serviceProvider` withdraws `tokens` amount. + * @dev Emitted when `delegator` delegated `tokens` to the `serviceProvider`, the delegator + * gets `shares` for the delegation pool proportionally to the tokens staked. + * This event is here for backwards compatibility, the tokens are delegated + * on the subgraph data service provision. + * @dev TODO(after transition period): move to IHorizonStakingMain */ - event StakeWithdrawn(address indexed serviceProvider, uint256 tokens); + event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); - /** - * @dev Emitted when `serviceProvider` locks `tokens` amount until `until`. - */ - event StakeLocked(address indexed serviceProvider, uint256 tokens, uint256 until); - - /** - * @dev Emitted when a service provider provisions staked tokens to a verifier - */ - event ProvisionCreated( - address indexed serviceProvider, - address indexed verifier, - uint256 tokens, - uint32 maxVerifierCut, - uint64 thawingPeriod - ); - - /** - * @dev Emitted when a service provider increases the tokens in a provision - */ - event ProvisionIncreased(address indexed serviceProvider, address indexed verifier, uint256 tokens); - - /** - * @dev Emitted when a thawing request is initiated by a service provider - */ - event ProvisionThawInitiated( - address indexed serviceProvider, - address indexed verifier, - uint256 tokens, - uint64 thawingUntil, - bytes32 indexed thawRequestId - ); + function getStake(address serviceProvider) external view returns (uint256); - /** - * @dev Emitted when a service provider removes tokens from a provision after thawing - */ - event ProvisionThawFulfilled( - address indexed serviceProvider, - address indexed verifier, - uint256 tokens, - bytes32 indexed thawRequestId - ); - - event ProvisionSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); - - event DelegationSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); - - event DelegationSlashingSkipped(address indexed serviceProvider, address indexed verifier, uint256 tokens); - - event VerifierTokensSent( - address indexed serviceProvider, - address indexed verifier, - address indexed destination, - uint256 tokens - ); - - event TokensDelegated( - address indexed serviceProvider, - address indexed verifier, - address indexed delegator, - uint256 tokens - ); - - event TokensUndelegated( - address indexed serviceProvider, - address indexed verifier, - address indexed delegator, - uint256 tokens - ); - - event DelegatedTokensWithdrawn( - address indexed serviceProvider, - address indexed verifier, - address indexed delegator, - uint256 tokens - ); - - event DelegationSlashingEnabled(bool enabled); - - event AllowedLockedVerifierSet(address verifier, bool allowed); - - event TokensAddedToDelegationPool(address indexed serviceProvider, address indexed verifier, uint256 tokens); - - event ProvisionParametersStaged( - address indexed serviceProvider, - address indexed verifier, - uint32 maxVerifierCut, - uint64 thawingPeriod - ); - - event ProvisionParametersSet( - address indexed serviceProvider, - address indexed verifier, - uint32 maxVerifierCut, - uint64 thawingPeriod - ); - - // deposit stake - function stake(uint256 tokens) external; - - function stakeTo(address serviceProvider, uint256 tokens) external; - - // can be called by anyone if the service provider has provisioned stake to this verifier - function stakeToProvision(address serviceProvider, address verifier, uint256 tokens) external; - - // create a provision - function provision( - address serviceProvider, - address verifier, - uint256 tokens, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) external; + function getDelegatedTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); - /** - * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period - * and will be slashable by the verifier. This is the main mechanism to provision stake to a data - * service, where the data service is the verifier. Only authorized verifiers can be used. - * This function can be called by the service provider or by an operator authorized by the provider - * for this specific verifier. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) - * @param tokens The amount of tokens that will be locked and slashable - * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing - * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision - */ - function provisionLocked( + function getTokensAvailable( address serviceProvider, address verifier, - uint256 tokens, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) external; - - // initiate a thawing to remove tokens from a provision - function thaw(address serviceProvider, address verifier, uint256 tokens) external returns (bytes32); + uint32 delegationRatio + ) external view returns (uint256); - // add more tokens from idle stake to an existing provision - function addToProvision(address serviceProvider, address verifier, uint256 tokens) external; + function getServiceProvider( + address serviceProvider + ) external view returns (IHorizonStakingTypes.ServiceProvider memory); - // moves thawed stake from a provision back into the provider's available stake - function deprovision(address serviceProvider, address verifier, uint256 tokens) external; + function getMaxThawingPeriod() external view returns (uint64); - // moves thawed stake from one provision into another provision - function reprovision(address serviceProvider, address oldVerifier, address newVerifier, uint256 tokens) external; - - // moves thawed stake back to the owner's account - stake is removed from the protocol - function unstake(uint256 tokens) external; - - // delegate tokens to a provider on a data service - function delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) external; - - // undelegate (thaw) delegated tokens from a provision - function undelegate(address serviceProvider, address verifier, uint256 shares) external; - - // withdraw delegated tokens after thawing - function withdrawDelegated( + function getDelegationPool( address serviceProvider, - address verifier, - address newServiceProvider, - uint256 minSharesForNewProvider - ) external; + address verifier + ) external view returns (IHorizonStakingTypes.DelegationPool memory); - function slash( + function getDelegation( + address delegator, address serviceProvider, - uint256 tokens, - uint256 tokensVerifier, - address verifierDestination - ) external; - - /** - * @notice Withdraw service provider tokens once the thawing period has passed. - * @dev This is only needed during the transition period while we still have - * a global lock. After that, unstake() will also withdraw. - */ - function withdraw() external; - - function setDelegationSlashingEnabled(bool enabled) external; + address verifier + ) external view returns (IHorizonStakingTypes.Delegation memory); - function setMaxThawingPeriod(uint64 maxThawingPeriod) external; + function getThawRequest(bytes32 thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory); - function setAllowedLockedVerifier(address verifier, bool allowed) external; - - /** - * @notice Add tokens to a delegation pool (without getting shares). - * Used by data services to pay delegation fees/rewards. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - * @param tokens The amount of tokens to add to the delegation pool - */ - function addToDelegationPool(address serviceProvider, address verifier, uint256 tokens) external; + function getProvision( + address serviceProvider, + address verifier + ) external view returns (IHorizonStakingTypes.Provision memory); - function setProvisionParameters( + function getDelegationFeeCut( address serviceProvider, address verifier, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) external; - - function acceptProvisionParameters(address serviceProvider) external; + IGraphPayments.PaymentTypes paymentType + ) external view returns (uint256); // staked tokens that are currently not provisioned, aka idle stake // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` function getIdleStake(address serviceProvider) external view returns (uint256 tokens); - /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param operator The address to check for auth - * @param serviceProvider The service provider on behalf of whom they're claiming to act - * @param verifier The verifier / data service on which they're claiming to act - */ - function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); - function getProviderTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); } diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol index 99ff66677..992ad7069 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol @@ -2,69 +2,165 @@ pragma solidity 0.8.24; -import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; -import { IGraphPayments } from "./IGraphPayments.sol"; +/** + * @title Base interface for the Staking contract. + * @dev This interface includes only what's implemented in the base Staking contract. + * It does not include the L1 and L2 specific functionality. It also does not include + * several functions that are implemented in the StakingExtension contract, and are called + * via delegatecall through the fallback function. See IStaking.sol for an interface + * that includes the full functionality. + */ +interface IHorizonStakingExtension { + /** + * @dev Allocate GRT tokens for the purpose of serving queries of a subgraph deployment + * An allocation is created in the allocate() function and closed in closeAllocation() + */ + struct Allocation { + address indexer; + bytes32 subgraphDeploymentID; + uint256 tokens; // Tokens allocated to a SubgraphDeployment + uint256 createdAtEpoch; // Epoch when it was created + uint256 closedAtEpoch; // Epoch when it was closed + uint256 collectedFees; // Collected fees for the allocation + uint256 DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase + uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc + uint256 distributedRebates; // Collected rebates that have been rebated + } -interface IHorizonStakingExtension is IHorizonStakingTypes { /** - * @dev Emitted when an operator is allowed or denied by a service provider for a particular data service + * @dev Possible states an allocation can be. + * States: + * - Null = indexer == address(0) + * - Active = not Null && tokens > 0 + * - Closed = Active && closedAtEpoch != 0 */ - event OperatorSet(address indexed serviceProvider, address indexed operator, address verifier, bool allowed); + enum AllocationState { + Null, + Active, + Closed + } - event DelegationFeeCutSet( - address indexed serviceProvider, - address indexed verifier, - IGraphPayments.PaymentTypes paymentType, - uint256 feeCut + /** + * @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`. + * An amount of `tokens` get unallocated from `subgraphDeploymentID`. + * This event also emits the POI (proof of indexing) submitted by the indexer. + * `isPublic` is true if the sender was someone other than the indexer. + */ + event AllocationClosed( + address indexed indexer, + bytes32 indexed subgraphDeploymentID, + uint256 epoch, + uint256 tokens, + address indexed allocationID, + address sender, + bytes32 poi, + bool isPublic ); /** - * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. - * @param operator Address to authorize or unauthorize - * @param verifier The verifier / data service on which they'll be allowed to operate - * @param allowed Whether the operator is authorized or not + * @dev Emitted when `indexer` collects a rebate on `subgraphDeploymentID` for `allocationID`. + * `epoch` is the protocol epoch the rebate was collected on + * The rebate is for `tokens` amount which are being provided by `assetHolder`; `queryFees` + * is the amount up for rebate after `curationFees` are distributed and `protocolTax` is burnt. + * `queryRebates` is the amount distributed to the `indexer` with `delegationFees` collected + * and sent to the delegation pool. */ - function setOperator(address operator, address verifier, bool allowed) external; - - // for vesting contracts - function setOperatorLocked(address operator, address verifier, bool allowed) external; + event RebateCollected( + address assetHolder, + address indexed indexer, + bytes32 indexed subgraphDeploymentID, + address indexed allocationID, + uint256 epoch, + uint256 tokens, + uint256 protocolTax, + uint256 curationFees, + uint256 queryFees, + uint256 queryRebates, + uint256 delegationRewards + ); - function setDelegationFeeCut( - address serviceProvider, - address verifier, - IGraphPayments.PaymentTypes paymentType, - uint256 feeCut - ) external; + /** + * @dev Emitted when `indexer` set `operator` access in the legacy contract, + * which now means only for the subgraph data service. + */ + event SetOperator(address indexed indexer, address indexed operator, bool allowed); - function getStake(address serviceProvider) external view returns (uint256); + /** + * @notice Set the address of the counterpart (L1 or L2) staking contract. + * @dev This function can only be called by the governor. + * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. + */ + function setCounterpartStakingAddress(address counterpart) external; - function getDelegatedTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); + /** + * @notice Close an allocation and free the staked tokens. + * To be eligible for rewards a proof of indexing must be presented. + * Presenting a bad proof is subject to slashable condition. + * To opt out of rewards set _poi to 0x0 + * @param allocationID The allocation identifier + * @param poi Proof of indexing submitted for the allocated period + */ + function closeAllocation(address allocationID, bytes32 poi) external; - function getTokensAvailable( - address serviceProvider, - address verifier, - uint32 delegationRatio - ) external view returns (uint256); + /** + * @notice Collect query fees from state channels and assign them to an allocation. + * Funds received are only accepted from a valid sender. + * @dev To avoid reverting on the withdrawal from channel flow this function will: + * 1) Accept calls with zero tokens. + * 2) Accept calls after an allocation passed the dispute period, in that case, all + * the received tokens are burned. + * @param tokens Amount of tokens to collect + * @param allocationID Allocation where the tokens will be assigned + */ + function collect(uint256 tokens, address allocationID) external; - function getServiceProvider(address serviceProvider) external view returns (ServiceProvider memory); + /** + * @notice Return true if operator is allowed for indexer. + * @param operator Address of the operator + * @param indexer Address of the indexer + * @return True if operator is allowed for indexer, false otherwise + */ + function isOperator(address operator, address indexer) external view returns (bool); - function getMaxThawingPeriod() external view returns (uint64); + /** + * @notice Getter that returns if an indexer has any stake. + * @param indexer Address of the indexer + * @return True if indexer has staked tokens + */ + function hasStake(address indexer) external view returns (bool); - function getDelegationPool(address serviceProvider, address verifier) external view returns (DelegationPool memory); + /** + * @notice Get the total amount of tokens staked by the indexer. + * @param indexer Address of the indexer + * @return Amount of tokens staked by the indexer + */ + function getIndexerStakedTokens(address indexer) external view returns (uint256); - function getDelegation( - address delegator, - address serviceProvider, - address verifier - ) external view returns (Delegation memory); + /** + * @notice Return the allocation by ID. + * @param allocationID Address used as allocation identifier + * @return Allocation data + */ + function getAllocation(address allocationID) external view returns (Allocation memory); - function getThawRequest(bytes32 thawRequestId) external view returns (ThawRequest memory); + /** + * @notice Return the current state of an allocation + * @param allocationID Allocation identifier + * @return AllocationState enum with the state of the allocation + */ + function getAllocationState(address allocationID) external view returns (AllocationState); - function getProvision(address serviceProvider, address verifier) external view returns (Provision memory); + /** + * @notice Return if allocationID is used. + * @param allocationID Address used as signer by the indexer for an allocation + * @return True if allocationID already used + */ + function isAllocation(address allocationID) external view returns (bool); - function getDelegationFeeCut( - address serviceProvider, - address verifier, - IGraphPayments.PaymentTypes paymentType - ) external view returns (uint256); + /** + * @notice Return the total amount of tokens allocated to subgraph. + * @param subgraphDeploymentID Deployment ID for the subgraph + * @return Total tokens allocated to subgraph + */ + function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view returns (uint256); } diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/IHorizonStakingMain.sol new file mode 100644 index 000000000..8146ed5cb --- /dev/null +++ b/packages/horizon/contracts/interfaces/IHorizonStakingMain.sol @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; +import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; + +interface IHorizonStakingMain is IHorizonStakingBase { + /** + * @dev Emitted when `serviceProvider` withdraws `tokens` amount. + */ + event StakeWithdrawn(address indexed serviceProvider, uint256 tokens); + + /** + * @dev Emitted when `serviceProvider` locks `tokens` amount until `until`. + */ + event StakeLocked(address indexed serviceProvider, uint256 tokens, uint256 until); + + /** + * @dev Emitted when a service provider provisions staked tokens to a verifier + */ + event ProvisionCreated( + address indexed serviceProvider, + address indexed verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + /** + * @dev Emitted when a service provider increases the tokens in a provision + */ + event ProvisionIncreased(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + /** + * @dev Emitted when a thawing request is initiated by a service provider + */ + event ProvisionThawInitiated( + address indexed serviceProvider, + address indexed verifier, + uint256 tokens, + uint64 thawingUntil, + bytes32 indexed thawRequestId + ); + + /** + * @dev Emitted when a service provider removes tokens from a provision after thawing + */ + event ProvisionThawFulfilled( + address indexed serviceProvider, + address indexed verifier, + uint256 tokens, + bytes32 indexed thawRequestId + ); + + event ProvisionSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event DelegationSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event DelegationSlashingSkipped(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event VerifierTokensSent( + address indexed serviceProvider, + address indexed verifier, + address indexed destination, + uint256 tokens + ); + + event TokensDelegated( + address indexed serviceProvider, + address indexed verifier, + address indexed delegator, + uint256 tokens + ); + + event TokensUndelegated( + address indexed serviceProvider, + address indexed verifier, + address indexed delegator, + uint256 tokens + ); + + event DelegatedTokensWithdrawn( + address indexed serviceProvider, + address indexed verifier, + address indexed delegator, + uint256 tokens + ); + + event DelegationSlashingEnabled(bool enabled); + + event AllowedLockedVerifierSet(address verifier, bool allowed); + + event TokensAddedToDelegationPool(address indexed serviceProvider, address indexed verifier, uint256 tokens); + + event ProvisionParametersStaged( + address indexed serviceProvider, + address indexed verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + event ProvisionParametersSet( + address indexed serviceProvider, + address indexed verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + /** + * @dev Emitted when an operator is allowed or denied by a service provider for a particular data service + */ + event OperatorSet(address indexed serviceProvider, address indexed operator, address verifier, bool allowed); + + event DelegationFeeCutSet( + address indexed serviceProvider, + address indexed verifier, + IGraphPayments.PaymentTypes paymentType, + uint256 feeCut + ); + + // deposit stake + function stake(uint256 tokens) external; + + function stakeTo(address serviceProvider, uint256 tokens) external; + + // can be called by anyone if the service provider has provisioned stake to this verifier + function stakeToProvision(address serviceProvider, address verifier, uint256 tokens) external; + + // create a provision + function provision( + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external; + + /** + * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period + * and will be slashable by the verifier. This is the main mechanism to provision stake to a data + * service, where the data service is the verifier. Only authorized verifiers can be used. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param tokens The amount of tokens that will be locked and slashable + * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + */ + function provisionLocked( + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external; + + // initiate a thawing to remove tokens from a provision + function thaw(address serviceProvider, address verifier, uint256 tokens) external returns (bytes32); + + // add more tokens from idle stake to an existing provision + function addToProvision(address serviceProvider, address verifier, uint256 tokens) external; + + // moves thawed stake from a provision back into the provider's available stake + function deprovision(address serviceProvider, address verifier, uint256 tokens) external; + + // moves thawed stake from one provision into another provision + function reprovision(address serviceProvider, address oldVerifier, address newVerifier, uint256 tokens) external; + + // moves thawed stake back to the owner's account - stake is removed from the protocol + function unstake(uint256 tokens) external; + + // delegate tokens to a provider on a data service + function delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) external; + + // undelegate (thaw) delegated tokens from a provision + function undelegate(address serviceProvider, address verifier, uint256 shares) external; + + // withdraw delegated tokens after thawing + function withdrawDelegated( + address serviceProvider, + address verifier, + address newServiceProvider, + uint256 minSharesForNewProvider + ) external; + + function slash( + address serviceProvider, + uint256 tokens, + uint256 tokensVerifier, + address verifierDestination + ) external; + + /** + * @notice Withdraw service provider tokens once the thawing period has passed. + * @dev This is only needed during the transition period while we still have + * a global lock. After that, unstake() will also withdraw. + */ + function withdraw() external; + + function setDelegationSlashingEnabled(bool enabled) external; + + function setMaxThawingPeriod(uint64 maxThawingPeriod) external; + + function setAllowedLockedVerifier(address verifier, bool allowed) external; + + /** + * @notice Add tokens to a delegation pool (without getting shares). + * Used by data services to pay delegation fees/rewards. + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to add to the delegation pool + */ + function addToDelegationPool(address serviceProvider, address verifier, uint256 tokens) external; + + function setProvisionParameters( + address serviceProvider, + address verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external; + + function acceptProvisionParameters(address serviceProvider) external; + + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param operator The address to check for auth + * @param serviceProvider The service provider on behalf of whom they're claiming to act + * @param verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); + + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @param operator Address to authorize or unauthorize + * @param verifier The verifier / data service on which they'll be allowed to operate + * @param allowed Whether the operator is authorized or not + */ + function setOperator(address operator, address verifier, bool allowed) external; + + // for vesting contracts + function setOperatorLocked(address operator, address verifier, bool allowed) external; + + function setDelegationFeeCut( + address serviceProvider, + address verifier, + IGraphPayments.PaymentTypes paymentType, + uint256 feeCut + ) external; +} diff --git a/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol b/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol deleted file mode 100644 index bf5efbf0d..000000000 --- a/packages/horizon/contracts/interfaces/IStakingBackwardsCompatibility.sol +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity 0.8.24; - -/** - * @title Base interface for the Staking contract. - * @dev This interface includes only what's implemented in the base Staking contract. - * It does not include the L1 and L2 specific functionality. It also does not include - * several functions that are implemented in the StakingExtension contract, and are called - * via delegatecall through the fallback function. See IStaking.sol for an interface - * that includes the full functionality. - */ -interface IStakingBackwardsCompatibility { - /** - * @dev Allocate GRT tokens for the purpose of serving queries of a subgraph deployment - * An allocation is created in the allocate() function and closed in closeAllocation() - */ - struct Allocation { - address indexer; - bytes32 subgraphDeploymentID; - uint256 tokens; // Tokens allocated to a SubgraphDeployment - uint256 createdAtEpoch; // Epoch when it was created - uint256 closedAtEpoch; // Epoch when it was closed - uint256 collectedFees; // Collected fees for the allocation - uint256 DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase - uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc - uint256 distributedRebates; // Collected rebates that have been rebated - } - - /** - * @dev Possible states an allocation can be. - * States: - * - Null = indexer == address(0) - * - Active = not Null && tokens > 0 - * - Closed = Active && closedAtEpoch != 0 - */ - enum AllocationState { - Null, - Active, - Closed - } - - /** - * @dev Emitted when `delegator` delegated `tokens` to the `serviceProvider`, the delegator - * gets `shares` for the delegation pool proportionally to the tokens staked. - * This event is here for backwards compatibility, the tokens are delegated - * on the subgraph data service provision. - */ - event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); - - /** - * @dev Emitted when `serviceProvider` stakes `tokens` amount. - */ - event StakeDeposited(address indexed serviceProvider, uint256 tokens); - - /** - * @dev Emitted when `serviceProvider` withdraws `tokens` amount. - */ - event StakeWithdrawn(address indexed serviceProvider, uint256 tokens); - - /** - * @dev Emitted when `serviceProvider` locks `tokens` amount until `until`. - */ - event StakeLocked(address indexed serviceProvider, uint256 tokens, uint256 until); - - /** - * @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`. - * An amount of `tokens` get unallocated from `subgraphDeploymentID`. - * This event also emits the POI (proof of indexing) submitted by the indexer. - * `isPublic` is true if the sender was someone other than the indexer. - */ - event AllocationClosed( - address indexed indexer, - bytes32 indexed subgraphDeploymentID, - uint256 epoch, - uint256 tokens, - address indexed allocationID, - address sender, - bytes32 poi, - bool isPublic - ); - - /** - * @dev Emitted when `indexer` collects a rebate on `subgraphDeploymentID` for `allocationID`. - * `epoch` is the protocol epoch the rebate was collected on - * The rebate is for `tokens` amount which are being provided by `assetHolder`; `queryFees` - * is the amount up for rebate after `curationFees` are distributed and `protocolTax` is burnt. - * `queryRebates` is the amount distributed to the `indexer` with `delegationFees` collected - * and sent to the delegation pool. - */ - event RebateCollected( - address assetHolder, - address indexed indexer, - bytes32 indexed subgraphDeploymentID, - address indexed allocationID, - uint256 epoch, - uint256 tokens, - uint256 protocolTax, - uint256 curationFees, - uint256 queryFees, - uint256 queryRebates, - uint256 delegationRewards - ); - - /** - * @dev Emitted when `indexer` set `operator` access in the legacy contract, - * which now means only for the subgraph data service. - */ - event SetOperator(address indexed indexer, address indexed operator, bool allowed); - - /** - * @notice Set the address of the counterpart (L1 or L2) staking contract. - * @dev This function can only be called by the governor. - * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. - */ - function setCounterpartStakingAddress(address counterpart) external; - - /** - * @notice Close an allocation and free the staked tokens. - * To be eligible for rewards a proof of indexing must be presented. - * Presenting a bad proof is subject to slashable condition. - * To opt out of rewards set _poi to 0x0 - * @param allocationID The allocation identifier - * @param poi Proof of indexing submitted for the allocated period - */ - function closeAllocation(address allocationID, bytes32 poi) external; - - /** - * @notice Collect query fees from state channels and assign them to an allocation. - * Funds received are only accepted from a valid sender. - * @dev To avoid reverting on the withdrawal from channel flow this function will: - * 1) Accept calls with zero tokens. - * 2) Accept calls after an allocation passed the dispute period, in that case, all - * the received tokens are burned. - * @param tokens Amount of tokens to collect - * @param allocationID Allocation where the tokens will be assigned - */ - function collect(uint256 tokens, address allocationID) external; - - /** - * @notice Return true if operator is allowed for indexer. - * @param operator Address of the operator - * @param indexer Address of the indexer - * @return True if operator is allowed for indexer, false otherwise - */ - function isOperator(address operator, address indexer) external view returns (bool); - - /** - * @notice Getter that returns if an indexer has any stake. - * @param indexer Address of the indexer - * @return True if indexer has staked tokens - */ - function hasStake(address indexer) external view returns (bool); - - /** - * @notice Get the total amount of tokens staked by the indexer. - * @param indexer Address of the indexer - * @return Amount of tokens staked by the indexer - */ - function getIndexerStakedTokens(address indexer) external view returns (uint256); - - /** - * @notice Return the allocation by ID. - * @param allocationID Address used as allocation identifier - * @return Allocation data - */ - function getAllocation(address allocationID) external view returns (Allocation memory); - - /** - * @notice Return the current state of an allocation - * @param allocationID Allocation identifier - * @return AllocationState enum with the state of the allocation - */ - function getAllocationState(address allocationID) external view returns (AllocationState); - - /** - * @notice Return if allocationID is used. - * @param allocationID Address used as signer by the indexer for an allocation - * @return True if allocationID already used - */ - function isAllocation(address allocationID) external view returns (bool); - - /** - * @notice Return the total amount of tokens allocated to subgraph. - * @param subgraphDeploymentID Deployment ID for the subgraph - * @return Total tokens allocated to subgraph - */ - function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view returns (uint256); -} diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 73707f623..c780c3880 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -2,17 +2,16 @@ pragma solidity 0.8.24; -import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; -import { IHorizonStakingBase } from "../interfaces/IHorizonStakingBase.sol"; +import { IHorizonStakingMain } from "../interfaces/IHorizonStakingMain.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; -import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; -import { Managed } from "./utilities/Managed.sol"; -import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; +import { HorizonStakingBase } from "./HorizonStakingBase.sol"; /** * @title HorizonStaking contract @@ -22,7 +21,7 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; * It uses a HorizonStakingExtension contract to implement the full IHorizonStaking interface through delegatecalls. * This is due to the contract size limit on Arbitrum (24kB like mainnet). */ -contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV1Storage, IHorizonStakingBase { +contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { using TokenUtils for IGraphToken; using PPMMath for uint256; @@ -45,7 +44,6 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV uint256 private constant MIN_DELEGATION = 1e18; address private immutable STAKING_EXTENSION_ADDRESS; - address private immutable SUBGRAPH_DATA_SERVICE_ADDRESS; error HorizonStakingInvalidVerifier(address verifier); error HorizonStakingVerifierAlreadyAllowed(address verifier); @@ -71,9 +69,8 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV address controller, address stakingExtensionAddress, address subgraphDataServiceAddress - ) Managed(controller) { + ) HorizonStakingBase(controller, subgraphDataServiceAddress) { STAKING_EXTENSION_ADDRESS = stakingExtensionAddress; - SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; } /** @@ -119,6 +116,40 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV stakeTo(msg.sender, tokens); } + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @param operator Address to authorize or unauthorize + * @param verifier The verifier / data service on which they'll be allowed to operate + * @param allowed Whether the operator is authorized or not + */ + function setOperator(address operator, address verifier, bool allowed) external override { + require(operator != msg.sender, "operator == sender"); + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + _legacyOperatorAuth[msg.sender][operator] = allowed; + } else { + _operatorAuth[msg.sender][verifier][operator] = allowed; + } + emit OperatorSet(msg.sender, operator, verifier, allowed); + } + + // for vesting contracts + function setOperatorLocked(address operator, address verifier, bool allowed) external override { + require(operator != msg.sender, "operator == sender"); + require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); + _operatorAuth[msg.sender][verifier][operator] = allowed; + emit OperatorSet(msg.sender, operator, verifier, allowed); + } + + function setDelegationFeeCut( + address serviceProvider, + address verifier, + IGraphPayments.PaymentTypes paymentType, + uint256 feeCut + ) external override { + delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; + emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); + } + function setProvisionParameters( address serviceProvider, address verifier, @@ -174,7 +205,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV uint32 maxVerifierCut, uint64 thawingPeriod ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { - if (getIdleStake(serviceProvider) < tokens) { + if (_getIdleStake(serviceProvider) < tokens) { revert HorizonStakingInsufficientCapacity(); } @@ -200,7 +231,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV uint32 maxVerifierCut, uint64 thawingPeriod ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { - if (getIdleStake(serviceProvider) < tokens) { + if (_getIdleStake(serviceProvider) < tokens) { revert HorizonStakingInsufficientCapacity(); } if (!_allowedLockedVerifiers[verifier]) { @@ -247,7 +278,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV sp.nextThawRequestNonce += 1; ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - require(getProviderTokensAvailable(serviceProvider, verifier) >= tokens, "insufficient tokens available"); + require(_getProviderTokensAvailable(serviceProvider, verifier) >= tokens, "insufficient tokens available"); prov.tokensThawing = prov.tokensThawing + tokens; if (prov.sharesThawing == 0) { @@ -321,7 +352,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV if (tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } - if (getIdleStake(serviceProvider) < tokens) { + if (_getIdleStake(serviceProvider) < tokens) { revert HorizonStakingInsufficientCapacity(); } @@ -415,12 +446,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV tokensToSlash = tokensToSlash - providerTokensSlashed; if (tokensToSlash > 0) { - DelegationPoolInternal storage pool; - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = _legacyDelegationPools[serviceProvider]; - } else { - pool = _delegationPools[serviceProvider][verifier]; - } + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); if (delegationSlashingEnabled) { require(pool.tokens >= tokensToSlash, "insufficient delegated tokens"); _graphToken().burnTokens(tokensToSlash); @@ -481,12 +507,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV if (tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } - DelegationPoolInternal storage pool; - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = _legacyDelegationPools[serviceProvider]; - } else { - pool = _delegationPools[serviceProvider][verifier]; - } + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); pool.tokens = pool.tokens + tokens; emit TokensAddedToDelegationPool(serviceProvider, verifier, tokens); } @@ -507,30 +528,6 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV emit ParameterUpdated("maxThawingPeriod"); } - /** - * @notice Get the amount of service provider's tokens in a provision that have finished thawing - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - */ - function getThawedTokens(address serviceProvider, address verifier) external view returns (uint256) { - Provision storage prov = _provisions[serviceProvider][verifier]; - if (prov.nThawRequests == 0) { - return 0; - } - bytes32 thawRequestId = prov.firstThawRequestId; - uint256 tokens = 0; - while (thawRequestId != bytes32(0)) { - ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - if (thawRequest.thawingUntil <= block.timestamp) { - tokens += (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; - } else { - break; - } - thawRequestId = thawRequest.next; - } - return tokens; - } - /** * @notice Deposit tokens on the service provider stake, on behalf of the service provider. * @param serviceProvider Address of the service provider @@ -563,12 +560,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV // the shares are burned and replaced with shares in the thawing pool function undelegate(address serviceProvider, address verifier, uint256 shares) public override notPartialPaused { require(shares > 0, "!shares"); - DelegationPoolInternal storage pool; - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = _legacyDelegationPools[serviceProvider]; - } else { - pool = _delegationPools[serviceProvider][verifier]; - } + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); Delegation storage delegation = pool.delegators[msg.sender]; require(delegation.shares >= shares, "!shares-avail"); @@ -614,12 +606,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV address newServiceProvider, uint256 minSharesForNewProvider ) public override notPartialPaused { - DelegationPoolInternal storage pool; - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = _legacyDelegationPools[serviceProvider]; - } else { - pool = _delegationPools[serviceProvider][verifier]; - } + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); Delegation storage delegation = pool.delegators[msg.sender]; uint256 thawedTokens = 0; @@ -679,24 +666,6 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV } } - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) public view override returns (uint256 tokens) { - return - _serviceProviders[serviceProvider].tokensStaked - - _serviceProviders[serviceProvider].tokensProvisioned - - _serviceProviders[serviceProvider].__DEPRECATED_tokensLocked; - } - - // provisioned tokens from the service provider that are not being thawed - // `Provision.tokens - Provision.tokensThawing` - function getProviderTokensAvailable( - address serviceProvider, - address verifier - ) public view override returns (uint256) { - return _provisions[serviceProvider][verifier].tokens - _provisions[serviceProvider][verifier].tokensThawing; - } - function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) internal { if (_tokens == 0) { revert HorizonStakingInvalidZeroTokens(); @@ -709,12 +678,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); } - DelegationPoolInternal storage pool; - if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = _legacyDelegationPools[_serviceProvider]; - } else { - pool = _delegationPools[_serviceProvider][_verifier]; - } + DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); Delegation storage delegation = pool.delegators[msg.sender]; // Calculate shares to issue @@ -813,7 +777,7 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV if (prov.createdAt == 0) { revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); } - if (getIdleStake(_serviceProvider) < _tokens) { + if (_getIdleStake(_serviceProvider) < _tokens) { revert HorizonStakingInsufficientCapacity(); } @@ -824,19 +788,6 @@ contract HorizonStaking is GraphUpgradeable, Multicall, Managed, HorizonStakingV emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); } - /** - * @dev Stake tokens on the service provider. - * TODO: Move to HorizonStaking after the transition period - * @param _serviceProvider Address of staking party - * @param _tokens Amount of tokens to stake - */ - function _stake(address _serviceProvider, uint256 _tokens) internal { - // Deposit tokens into the service provider stake - _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; - - emit StakeDeposited(_serviceProvider, _tokens); - } - /** * @dev Withdraw service provider tokens once the thawing period has passed. * @param _serviceProvider Address of service provider to withdraw funds from diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol new file mode 100644 index 000000000..cd54932b8 --- /dev/null +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.24; + +import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; +import { IHorizonStakingBase } from "../interfaces/IHorizonStakingBase.sol"; +import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; + +import { MathUtils } from "../libraries/MathUtils.sol"; + +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; +import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; +import { Managed } from "./utilities/Managed.sol"; +import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; + +/** + * @title L2Staking contract + * @dev This contract is the L2 variant of the Staking contract. It adds a function + * to receive an service provider'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. + */ +abstract contract HorizonStakingBase is + Multicall, + Managed, + HorizonStakingV1Storage, + GraphUpgradeable, + IHorizonStakingTypes, + IHorizonStakingBase +{ + address internal immutable SUBGRAPH_DATA_SERVICE_ADDRESS; + + constructor(address controller, address subgraphDataServiceAddress) Managed(controller) { + SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; + } + + /** + * @notice Receive ETH into the Staking contract: this will always revert + * @dev This function is only here to prevent ETH from being sent to the contract + */ + receive() external payable { + revert("RECEIVE_ETH_NOT_ALLOWED"); + } + + // total staked tokens to the provider + // `ServiceProvider.tokensStaked + function getStake(address serviceProvider) external view override returns (uint256) { + return _serviceProviders[serviceProvider].tokensStaked; + } + + // provisioned tokens that are not being thawed (including provider tokens and delegation) + function getTokensAvailable( + address serviceProvider, + address verifier, + uint32 delegationRatio + ) external view override returns (uint256) { + uint256 providerTokens = _provisions[serviceProvider][verifier].tokens; + uint256 providerThawingTokens = _provisions[serviceProvider][verifier].tokensThawing; + uint256 tokensDelegatedMax = (providerTokens - providerThawingTokens) * (uint256(delegationRatio)); + uint256 tokensDelegatedCapacity = MathUtils.min( + getDelegatedTokensAvailable(serviceProvider, verifier), + tokensDelegatedMax + ); + return providerTokens - providerThawingTokens + tokensDelegatedCapacity; + } + + function getServiceProvider(address serviceProvider) external view override returns (ServiceProvider memory) { + ServiceProvider memory sp; + ServiceProviderInternal storage spInternal = _serviceProviders[serviceProvider]; + sp.tokensStaked = spInternal.tokensStaked; + sp.tokensProvisioned = spInternal.tokensProvisioned; + sp.nextThawRequestNonce = spInternal.nextThawRequestNonce; + return sp; + } + + function getMaxThawingPeriod() external view override returns (uint64) { + return _maxThawingPeriod; + } + + function getDelegationPool( + address serviceProvider, + address verifier + ) external view override returns (DelegationPool memory) { + DelegationPool memory pool; + DelegationPoolInternal storage poolInternal = _getDelegationPool(serviceProvider, verifier); + pool.tokens = poolInternal.tokens; + pool.shares = poolInternal.shares; + pool.tokensThawing = poolInternal.tokensThawing; + pool.sharesThawing = poolInternal.sharesThawing; + return pool; + } + + function getDelegation( + address delegator, + address serviceProvider, + address verifier + ) external view override returns (Delegation memory) { + DelegationPoolInternal storage poolInternal = _getDelegationPool(serviceProvider, verifier); + return poolInternal.delegators[delegator]; + } + + function getThawRequest(bytes32 thawRequestId) external view returns (ThawRequest memory) { + return _thawRequests[thawRequestId]; + } + + function getProvision(address serviceProvider, address verifier) external view override returns (Provision memory) { + return _provisions[serviceProvider][verifier]; + } + + function getDelegationFeeCut( + address serviceProvider, + address verifier, + IGraphPayments.PaymentTypes paymentType + ) external view override returns (uint256) { + return delegationFeeCut[serviceProvider][verifier][paymentType]; + } + + // provisioned tokens from delegators that are not being thawed + // `Provision.delegatedTokens - Provision.delegatedTokensThawing` + function getDelegatedTokensAvailable( + address serviceProvider, + address verifier + ) public view override returns (uint256) { + DelegationPoolInternal storage poolInternal = _getDelegationPool(serviceProvider, verifier); + return poolInternal.tokens - poolInternal.tokensThawing; + } + + // staked tokens that are currently not provisioned, aka idle stake + // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` + function getIdleStake(address serviceProvider) external view override returns (uint256 tokens) { + return _getIdleStake(serviceProvider); + } + + // provisioned tokens from the service provider that are not being thawed + // `Provision.tokens - Provision.tokensThawing` + function getProviderTokensAvailable( + address serviceProvider, + address verifier + ) external view override returns (uint256) { + return _getProviderTokensAvailable(serviceProvider, verifier); + } + + /** + * @notice Get the amount of service provider's tokens in a provision that have finished thawing + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + */ + function getThawedTokens(address serviceProvider, address verifier) external view returns (uint256) { + Provision storage prov = _provisions[serviceProvider][verifier]; + if (prov.nThawRequests == 0) { + return 0; + } + bytes32 thawRequestId = prov.firstThawRequestId; + uint256 tokens = 0; + while (thawRequestId != bytes32(0)) { + ThawRequest storage thawRequest = _thawRequests[thawRequestId]; + if (thawRequest.thawingUntil <= block.timestamp) { + tokens += (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; + } else { + break; + } + thawRequestId = thawRequest.next; + } + return tokens; + } + + /** + * @notice Deposit tokens into the service provider stake. + * @dev TODO(after transition period): move to HorizonStaking + * @param _serviceProvider Address of staking party + * @param _tokens Amount of tokens to stake + */ + function _stake(address _serviceProvider, uint256 _tokens) internal { + _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; + emit StakeDeposited(_serviceProvider, _tokens); + } + + function _getDelegationPool( + address _serviceProvider, + address _verifier + ) internal view returns (DelegationPoolInternal storage) { + IHorizonStakingTypes.DelegationPoolInternal storage pool; + if (_verifier == _serviceProvider) { + pool = _legacyDelegationPools[_serviceProvider]; + } else { + pool = _delegationPools[_serviceProvider][_verifier]; + } + return pool; + } + + function etIdleStake(address serviceProvider) public view returns (uint256 tokens) { + return + _serviceProviders[serviceProvider].tokensStaked - + _serviceProviders[serviceProvider].tokensProvisioned - + _serviceProviders[serviceProvider].__DEPRECATED_tokensLocked; + } + + function gtProviderTokensAvailable(address serviceProvider, address verifier) public view returns (uint256) { + return _provisions[serviceProvider][verifier].tokens - _provisions[serviceProvider][verifier].tokensThawing; + } +} diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index c73cc9de7..71cfd3dc6 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -2,22 +2,37 @@ pragma solidity 0.8.24; -import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; -import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; +import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; +import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingExtension } from "../interfaces/IHorizonStakingExtension.sol"; -import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; +import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; +import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; +import { ExponentialRebates } from "./libraries/ExponentialRebates.sol"; +import { PPMMath } from "../libraries/PPMMath.sol"; -import { StakingBackwardsCompatibility } from "./StakingBackwardsCompatibility.sol"; +import { HorizonStakingBase } from "./HorizonStakingBase.sol"; +import { Managed } from "./utilities/Managed.sol"; +import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; /** - * @title L2Staking contract - * @dev This contract is the L2 variant of the Staking contract. It adds a function - * to receive an service provider'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. + * @title Base Staking contract + * @dev 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 + * and L2Staking on Arbitrum. + * Note that this contract delegates part of its functionality to a StakingExtension contract. + * This is due to the 24kB contract size limit on Ethereum. */ -contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBase, IHorizonStakingExtension { +contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2StakingBase, IHorizonStakingExtension { + using TokenUtils for IGraphToken; + using PPMMath for uint256; + /// @dev Minimum amount of tokens that can be delegated uint256 private constant MINIMUM_DELEGATION = 1e18; @@ -32,39 +47,7 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas constructor( address controller, address subgraphDataServiceAddress - ) StakingBackwardsCompatibility(controller, subgraphDataServiceAddress) {} - - /** - * @notice Receive ETH into the Staking contract: this will always revert - * @dev This function is only here to prevent ETH from being sent to the contract - */ - receive() external payable { - revert("RECEIVE_ETH_NOT_ALLOWED"); - } - - /** - * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. - * @param operator Address to authorize or unauthorize - * @param verifier The verifier / data service on which they'll be allowed to operate - * @param allowed Whether the operator is authorized or not - */ - function setOperator(address operator, address verifier, bool allowed) external override { - require(operator != msg.sender, "operator == sender"); - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - _legacyOperatorAuth[msg.sender][operator] = allowed; - } else { - _operatorAuth[msg.sender][verifier][operator] = allowed; - } - emit OperatorSet(msg.sender, operator, verifier, allowed); - } - - // for vesting contracts - function setOperatorLocked(address operator, address verifier, bool allowed) external override { - require(operator != msg.sender, "operator == sender"); - require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); - _operatorAuth[msg.sender][verifier][operator] = allowed; - emit OperatorSet(msg.sender, operator, verifier, allowed); - } + ) HorizonStakingBase(controller, subgraphDataServiceAddress) {} /** * @notice Receive tokens with a callhook from the bridge. @@ -101,111 +84,214 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas } } - function setDelegationFeeCut( - address serviceProvider, - address verifier, - IGraphPayments.PaymentTypes paymentType, - uint256 feeCut - ) external override { - delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; - emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); + /** + * @notice Set the address of the counterpart (L1 or L2) staking contract. + * @dev This function can only be called by the governor. + * TODO: Remove after L2 transition period + * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. + */ + function setCounterpartStakingAddress(address counterpart) external override onlyGovernor { + _counterpartStakingAddress = counterpart; + emit ParameterUpdated("counterpartStakingAddress"); } - // total staked tokens to the provider - // `ServiceProvider.tokensStaked - function getStake(address serviceProvider) external view override returns (uint256) { - return _serviceProviders[serviceProvider].tokensStaked; + /** + * @notice Close an allocation and free the staked tokens. + * To be eligible for rewards a proof of indexing must be presented. + * Presenting a bad proof is subject to slashable condition. + * To opt out of rewards set _poi to 0x0 + * @dev TODO: Remove after Horizon transition period + * @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); } - // provisioned tokens that are not being thawed (including provider tokens and delegation) - function getTokensAvailable( - address serviceProvider, - address verifier, - uint32 delegationRatio - ) external view override returns (uint256) { - uint256 providerTokens = _provisions[serviceProvider][verifier].tokens; - uint256 providerThawingTokens = _provisions[serviceProvider][verifier].tokensThawing; - uint256 tokensDelegatedMax = (providerTokens - providerThawingTokens) * (uint256(delegationRatio)); - uint256 tokensDelegatedCapacity = MathUtils.min( - getDelegatedTokensAvailable(serviceProvider, verifier), - tokensDelegatedMax + /** + * @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. + * 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. + * TODO: Remove after Horizon transition period + * @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 + require(allocationID != address(0), "!alloc"); + + // Allocation must exist + AllocationState allocState = _getAllocationState(allocationID); + require(allocState != AllocationState.Null, "!collect"); + + // If the query fees are zero, we don't want to revert + // but we also don't need to do anything, so just return + if (tokens == 0) { + return; + } + + Allocation storage alloc = __DEPRECATED_allocations[allocationID]; + bytes32 subgraphDeploymentID = alloc.subgraphDeploymentID; + + uint256 queryFees = tokens; // Tokens collected from the channel + uint256 protocolTax = 0; // Tokens burnt as protocol tax + uint256 curationFees = 0; // Tokens distributed to curators as curation fees + uint256 queryRebates = 0; // Tokens to distribute to indexer + uint256 delegationRewards = 0; // Tokens to distribute to delegators + + { + // -- Pull tokens from the sender -- + _graphToken().pullTokens(msg.sender, queryFees); + + // -- Collect protocol tax -- + protocolTax = _collectTax(queryFees, __DEPRECATED_protocolPercentage); + queryFees = queryFees - protocolTax; + + // -- Collect curation fees -- + // Only if the subgraph deployment is curated + curationFees = _collectCurationFees(subgraphDeploymentID, queryFees, __DEPRECATED_curationPercentage); + queryFees = queryFees - curationFees; + + // -- Process rebate reward -- + // Using accumulated fees and subtracting previously distributed rebates + // allows for multiple vouchers to be collected while following the rebate formula + alloc.collectedFees = alloc.collectedFees + queryFees; + + // No rebates if indexer has no stake or if lambda is zero + uint256 newRebates = (alloc.tokens == 0 || __DEPRECATED_lambdaNumerator == 0) + ? 0 + : ExponentialRebates.exponentialRebates( + alloc.collectedFees, + alloc.tokens, + __DEPRECATED_alphaNumerator, + __DEPRECATED_alphaDenominator, + __DEPRECATED_lambdaNumerator, + __DEPRECATED_lambdaDenominator + ); + + // -- Ensure rebates to distribute are within bounds -- + // Indexers can become under or over rebated if rebate parameters (alpha, lambda) + // change between successive collect calls for the same allocation + + // Ensure rebates to distribute are not negative (indexer is over-rebated) + queryRebates = MathUtils.diffOrZero(newRebates, alloc.distributedRebates); + + // Ensure rebates to distribute are not greater than available (indexer is under-rebated) + queryRebates = MathUtils.min(queryRebates, queryFees); + + // -- Burn rebates remanent -- + _graphToken().burnTokens(queryFees - queryRebates); + + // -- Distribute rebates -- + if (queryRebates > 0) { + alloc.distributedRebates = alloc.distributedRebates + queryRebates; + + // -- Collect delegation rewards into the delegation pool -- + delegationRewards = _collectDelegationQueryRewards(alloc.indexer, queryRebates); + queryRebates = queryRebates - delegationRewards; + + // -- Transfer or restake rebates -- + _sendRewards(queryRebates, alloc.indexer, __DEPRECATED_rewardsDestination[alloc.indexer] == address(0)); + } + } + + emit RebateCollected( + msg.sender, + alloc.indexer, + subgraphDeploymentID, + allocationID, + _graphEpochManager().currentEpoch(), + tokens, + protocolTax, + curationFees, + queryFees, + queryRebates, + delegationRewards ); - return providerTokens - providerThawingTokens + tokensDelegatedCapacity; } - function getServiceProvider(address serviceProvider) external view override returns (ServiceProvider memory) { - ServiceProvider memory sp; - ServiceProviderInternal storage spInternal = _serviceProviders[serviceProvider]; - sp.tokensStaked = spInternal.tokensStaked; - sp.tokensProvisioned = spInternal.tokensProvisioned; - sp.nextThawRequestNonce = spInternal.nextThawRequestNonce; - return sp; + /** + * @notice Return if allocationID is used. + * @dev TODO: Remove after Horizon transition period + * @param allocationID Address used as signer by the indexer for an allocation + * @return True if allocationID already used + */ + function isAllocation(address allocationID) external view override returns (bool) { + return _getAllocationState(allocationID) != AllocationState.Null; } - function getMaxThawingPeriod() external view override returns (uint64) { - return _maxThawingPeriod; + /** + * @notice Return the allocation by ID. + * @dev TODO: Remove after Horizon transition period + * @param allocationID Address used as allocation identifier + * @return Allocation data + */ + function getAllocation(address allocationID) external view override returns (Allocation memory) { + return __DEPRECATED_allocations[allocationID]; } - function getDelegationPool( - address serviceProvider, - address verifier - ) external view override returns (DelegationPool memory) { - DelegationPool memory pool; - DelegationPoolInternal storage poolInternal; - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - poolInternal = _legacyDelegationPools[serviceProvider]; - } else { - poolInternal = _delegationPools[serviceProvider][verifier]; - } - pool.tokens = poolInternal.tokens; - pool.shares = poolInternal.shares; - pool.tokensThawing = poolInternal.tokensThawing; - pool.sharesThawing = poolInternal.sharesThawing; - return pool; + /** + * @notice Return allocation data by ID. + * @dev To be called by the Rewards Manager to calculate rewards issuance. + * @dev TODO: Remove after Horizon transition period + * @param allocationID Address used as allocation identifier + * @return Allocation data + */ + function getAllocationData( + address allocationID + ) external view override returns (address, bytes32, uint256, uint256) { + Allocation memory allo = __DEPRECATED_allocations[allocationID]; + return (allo.indexer, allo.subgraphDeploymentID, allo.tokens, allo.accRewardsPerAllocatedToken); } - function getDelegation( - address delegator, - address serviceProvider, - address verifier - ) external view override returns (Delegation memory) { - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - return _legacyDelegationPools[serviceProvider].delegators[delegator]; - } else { - return _delegationPools[serviceProvider][verifier].delegators[delegator]; - } + /** + * @notice Return the current state of an allocation + * @dev TODO: Remove after Horizon transition period + * @param allocationID Allocation identifier + * @return AllocationState enum with the state of the allocation + */ + function getAllocationState(address allocationID) external view override returns (AllocationState) { + return _getAllocationState(allocationID); } - function getThawRequest(bytes32 thawRequestId) external view returns (ThawRequest memory) { - return _thawRequests[thawRequestId]; + /** + * @notice Return the total amount of tokens allocated to subgraph. + * @param subgraphDeploymentID Deployment ID for the subgraph + * @return Total tokens allocated to subgraph + */ + function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view override returns (uint256) { + return __DEPRECATED_subgraphAllocations[subgraphDeploymentID]; } - function getProvision(address serviceProvider, address verifier) external view override returns (Provision memory) { - return _provisions[serviceProvider][verifier]; + /** + * @notice Get the total amount of tokens staked by the indexer. + * @param indexer Address of the indexer + * @return Amount of tokens staked by the indexer + */ + function getIndexerStakedTokens(address indexer) external view override returns (uint256) { + return _serviceProviders[indexer].tokensStaked; } - function getDelegationFeeCut( - address serviceProvider, - address verifier, - IGraphPayments.PaymentTypes paymentType - ) external view override returns (uint256) { - return delegationFeeCut[serviceProvider][verifier][paymentType]; + /** + * @notice Getter that returns if an indexer has any stake. + * @param indexer Address of the indexer + * @return True if indexer has staked tokens + */ + function hasStake(address indexer) external view override returns (bool) { + return _serviceProviders[indexer].tokensStaked > 0; } - // provisioned tokens from delegators that are not being thawed - // `Provision.delegatedTokens - Provision.delegatedTokensThawing` - function getDelegatedTokensAvailable( - address serviceProvider, - address verifier - ) public view override returns (uint256) { - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - return - _legacyDelegationPools[serviceProvider].tokens - - (_legacyDelegationPools[serviceProvider].tokensThawing); - } - return - _delegationPools[serviceProvider][verifier].tokens - - (_delegationPools[serviceProvider][verifier].tokensThawing); + /** + * @notice (Legacy) Return true if operator is allowed for the service provider on the subgraph data service. + * @dev TODO: Delete after the transition period + * @param operator Address of the operator + * @param serviceProvider Address of the service provider + * @return True if operator is allowed for indexer, false otherwise + */ + function isOperator(address operator, address serviceProvider) public view override returns (bool) { + return _legacyOperatorAuth[serviceProvider][operator]; } /** @@ -237,8 +323,8 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas IL2StakingTypes.ReceiveDelegationData memory _delegationData ) internal { // Get the delegation pool of the indexer - DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; - Delegation storage delegation = pool.delegators[_delegationData.delegator]; + IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; + IHorizonStakingTypes.Delegation storage delegation = pool.delegators[_delegationData.delegator]; // Calculate shares to issue (without applying any delegation tax) uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / pool.tokens); @@ -260,4 +346,220 @@ contract HorizonStakingExtension is StakingBackwardsCompatibility, IL2StakingBas emit StakeDelegated(_delegationData.indexer, _delegationData.delegator, _tokens, shares); } } + + /** + * @dev Collect tax to burn for an amount of tokens. + * @param _tokens Total tokens received used to calculate the amount of tax to collect + * @param _percentage Percentage of tokens to burn as tax + * @return Amount of tax charged + */ + function _collectTax(uint256 _tokens, uint256 _percentage) private returns (uint256) { + uint256 tax = _tokens.mulPPMRoundUp(_percentage); + _graphToken().burnTokens(tax); // Burn tax if any + return tax; + } + + /** + * @dev 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 + */ + function _updateRewards(bytes32 _subgraphDeploymentID) private returns (uint256) { + return _graphRewardsManager().onSubgraphAllocationUpdate(_subgraphDeploymentID); + } + + /** + * @dev Assign rewards for the closed allocation to indexer and delegators. + * @param _allocationID Allocation + * @param _indexer Address of the indexer that did the allocation + */ + function _distributeRewards(address _allocationID, address _indexer) private { + // Automatically triggers update of rewards snapshot as allocation will change + // after this call. Take rewards mint tokens for the Staking contract to distribute + // between indexer and delegators + uint256 totalRewards = _graphRewardsManager().takeRewards(_allocationID); + if (totalRewards == 0) { + return; + } + + // Calculate delegation rewards and add them to the delegation pool + uint256 delegationRewards = _collectDelegationIndexingRewards(_indexer, totalRewards); + uint256 indexerRewards = totalRewards - delegationRewards; + + // Send the indexer rewards + _sendRewards(indexerRewards, _indexer, __DEPRECATED_rewardsDestination[_indexer] == address(0)); + } + + /** + * @dev Send rewards to the appropriate destination. + * @param _tokens Number of rewards tokens + * @param _beneficiary Address of the beneficiary of rewards + * @param _restake Whether to restake or not + */ + function _sendRewards(uint256 _tokens, address _beneficiary, bool _restake) private { + if (_tokens == 0) return; + + if (_restake) { + // Restake to place fees into the indexer stake + _stake(_beneficiary, _tokens); + } else { + // Transfer funds to the beneficiary's designated rewards destination if set + address destination = __DEPRECATED_rewardsDestination[_beneficiary]; + _graphToken().pushTokens(destination == address(0) ? _beneficiary : destination, _tokens); + } + } + + /** + * @dev Close an allocation and free the staked tokens. + * @param _allocationID The allocation identifier + * @param _poi Proof of indexing submitted for the allocated period + */ + function _closeAllocation(address _allocationID, bytes32 _poi) private { + // Allocation must exist and be active + AllocationState allocState = _getAllocationState(_allocationID); + require(allocState == AllocationState.Active, "!active"); + + // Get allocation + Allocation memory alloc = __DEPRECATED_allocations[_allocationID]; + + // Validate that an allocation cannot be closed before one epoch + alloc.closedAtEpoch = _graphEpochManager().currentEpoch(); + uint256 epochs = MathUtils.diffOrZero(alloc.closedAtEpoch, alloc.createdAtEpoch); + + // Indexer or operator can close an allocation + // Anyone is allowed to close ONLY under two concurrent conditions + // - After maxAllocationEpochs passed + // - When the allocation is for non-zero amount of tokens + bool isIndexer = isOperator(alloc.indexer, SUBGRAPH_DATA_SERVICE_ADDRESS); + if (epochs <= __DEPRECATED_maxAllocationEpochs || alloc.tokens == 0) { + require(isIndexer, "!auth"); + } + + // Close the allocation + __DEPRECATED_allocations[_allocationID].closedAtEpoch = alloc.closedAtEpoch; + + // -- Rewards Distribution -- + + // Process non-zero-allocation rewards tracking + if (alloc.tokens > 0) { + // Distribute rewards if proof of indexing was presented by the indexer or operator + if (isIndexer && _poi != 0) { + _distributeRewards(_allocationID, alloc.indexer); + } else { + _updateRewards(alloc.subgraphDeploymentID); + } + + // Free allocated tokens from use + _serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated = + _serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated - + alloc.tokens; + + // Track total allocations per subgraph + // Used for rewards calculations + __DEPRECATED_subgraphAllocations[alloc.subgraphDeploymentID] = + __DEPRECATED_subgraphAllocations[alloc.subgraphDeploymentID] - + alloc.tokens; + } + + emit AllocationClosed( + alloc.indexer, + alloc.subgraphDeploymentID, + alloc.closedAtEpoch, + alloc.tokens, + _allocationID, + msg.sender, + _poi, + !isIndexer + ); + } + + /** + * @dev 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 + * @return Amount of delegation rewards + */ + function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { + uint256 delegationRewards = 0; + IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; + if (pool.tokens > 0 && uint256(pool.__DEPRECATED_queryFeeCut).isValidPPM()) { + uint256 indexerCut = uint256(pool.__DEPRECATED_queryFeeCut).mulPPM(_tokens); + delegationRewards = _tokens - indexerCut; + pool.tokens = pool.tokens + delegationRewards; + } + return delegationRewards; + } + + /** + * @dev 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 + * @return Amount of delegation rewards + */ + function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { + uint256 delegationRewards = 0; + IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; + if (pool.tokens > 0 && uint256(pool.__DEPRECATED_indexingRewardCut).isValidPPM()) { + uint256 indexerCut = uint256(pool.__DEPRECATED_indexingRewardCut).mulPPM(_tokens); + delegationRewards = _tokens - indexerCut; + pool.tokens = pool.tokens + delegationRewards; + } + return delegationRewards; + } + + /** + * @dev Collect the curation fees for a subgraph deployment from an amount of tokens. + * This function transfer curation fees to the Curation contract by calling Curation.collect + * @param _subgraphDeploymentID Subgraph deployment to which the curation fees are related + * @param _tokens Total tokens received used to calculate the amount of fees to collect + * @param _curationCut Percentage of tokens to collect as fees + * @return Amount of curation fees + */ + function _collectCurationFees( + bytes32 _subgraphDeploymentID, + uint256 _tokens, + uint256 _curationCut + ) private returns (uint256) { + if (_tokens == 0) { + return 0; + } + + ICuration curation = _graphCuration(); + bool isCurationEnabled = _curationCut > 0 && address(curation) != address(0); + + if (isCurationEnabled && curation.isCurated(_subgraphDeploymentID)) { + uint256 curationFees = _tokens.mulPPMRoundUp(_curationCut); + if (curationFees > 0) { + // Transfer and call collect() + // This function transfer tokens to a trusted protocol contracts + // Then we call collect() to do the transfer bookeeping + _graphRewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); + _graphToken().pushTokens(address(curation), curationFees); + curation.collect(_subgraphDeploymentID, curationFees); + } + return curationFees; + } + return 0; + } + + /** + * @dev Return the current state of an allocation + * @param _allocationID Allocation identifier + * @return AllocationState enum with the state of the allocation + */ + function _getAllocationState(address _allocationID) private view returns (AllocationState) { + Allocation storage alloc = __DEPRECATED_allocations[_allocationID]; + + if (alloc.indexer == address(0)) { + return AllocationState.Null; + } + + if (alloc.createdAtEpoch != 0 && alloc.closedAtEpoch == 0) { + return AllocationState.Active; + } + + return AllocationState.Closed; + } } diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 5c85f910b..96af3a4fb 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; -import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; +import { IHorizonStakingExtension } from "../interfaces/IHorizonStakingExtension.sol"; import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; @@ -56,8 +56,7 @@ abstract contract HorizonStakingV1Storage { /// @dev Allocations : allocationID => Allocation /// Deprecated, now applied on the SubgraphService - mapping(address allocationId => IStakingBackwardsCompatibility.Allocation allocation) - internal __DEPRECATED_allocations; + mapping(address allocationId => IHorizonStakingExtension.Allocation allocation) internal __DEPRECATED_allocations; /// @dev Subgraph Allocations: subgraphDeploymentID => tokens /// Deprecated, now applied on the SubgraphService diff --git a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol b/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol deleted file mode 100644 index b0b46a9a5..000000000 --- a/packages/horizon/contracts/staking/StakingBackwardsCompatibility.sol +++ /dev/null @@ -1,482 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity 0.8.24; - -import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; -import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; -import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; -import { IStakingBackwardsCompatibility } from "../interfaces/IStakingBackwardsCompatibility.sol"; -import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; - -import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; -import { MathUtils } from "../libraries/MathUtils.sol"; -import { ExponentialRebates } from "./libraries/ExponentialRebates.sol"; -import { PPMMath } from "../libraries/PPMMath.sol"; - -import { Managed } from "./utilities/Managed.sol"; -import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; - -/** - * @title Base Staking contract - * @dev 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 - * and L2Staking on Arbitrum. - * Note that this contract delegates part of its functionality to a StakingExtension contract. - * This is due to the 24kB contract size limit on Ethereum. - */ -abstract contract StakingBackwardsCompatibility is - Managed, - HorizonStakingV1Storage, - IRewardsIssuer, - IStakingBackwardsCompatibility -{ - using TokenUtils for IGraphToken; - using PPMMath for uint256; - - address public immutable SUBGRAPH_DATA_SERVICE_ADDRESS; - - constructor(address controller, address subgraphDataServiceAddress) Managed(controller) { - SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; - } - - /** - * @notice Set the address of the counterpart (L1 or L2) staking contract. - * @dev This function can only be called by the governor. - * TODO: Remove after L2 transition period - * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. - */ - function setCounterpartStakingAddress(address counterpart) external override onlyGovernor { - _counterpartStakingAddress = counterpart; - emit ParameterUpdated("counterpartStakingAddress"); - } - - /** - * @notice Close an allocation and free the staked tokens. - * To be eligible for rewards a proof of indexing must be presented. - * Presenting a bad proof is subject to slashable condition. - * To opt out of rewards set _poi to 0x0 - * @dev TODO: Remove after Horizon transition period - * @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. - * 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. - * TODO: Remove after Horizon transition period - * @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 - require(allocationID != address(0), "!alloc"); - - // Allocation must exist - AllocationState allocState = _getAllocationState(allocationID); - require(allocState != AllocationState.Null, "!collect"); - - // If the query fees are zero, we don't want to revert - // but we also don't need to do anything, so just return - if (tokens == 0) { - return; - } - - Allocation storage alloc = __DEPRECATED_allocations[allocationID]; - bytes32 subgraphDeploymentID = alloc.subgraphDeploymentID; - - uint256 queryFees = tokens; // Tokens collected from the channel - uint256 protocolTax = 0; // Tokens burnt as protocol tax - uint256 curationFees = 0; // Tokens distributed to curators as curation fees - uint256 queryRebates = 0; // Tokens to distribute to indexer - uint256 delegationRewards = 0; // Tokens to distribute to delegators - - { - // -- Pull tokens from the sender -- - _graphToken().pullTokens(msg.sender, queryFees); - - // -- Collect protocol tax -- - protocolTax = _collectTax(queryFees, __DEPRECATED_protocolPercentage); - queryFees = queryFees - protocolTax; - - // -- Collect curation fees -- - // Only if the subgraph deployment is curated - curationFees = _collectCurationFees(subgraphDeploymentID, queryFees, __DEPRECATED_curationPercentage); - queryFees = queryFees - curationFees; - - // -- Process rebate reward -- - // Using accumulated fees and subtracting previously distributed rebates - // allows for multiple vouchers to be collected while following the rebate formula - alloc.collectedFees = alloc.collectedFees + queryFees; - - // No rebates if indexer has no stake or if lambda is zero - uint256 newRebates = (alloc.tokens == 0 || __DEPRECATED_lambdaNumerator == 0) - ? 0 - : ExponentialRebates.exponentialRebates( - alloc.collectedFees, - alloc.tokens, - __DEPRECATED_alphaNumerator, - __DEPRECATED_alphaDenominator, - __DEPRECATED_lambdaNumerator, - __DEPRECATED_lambdaDenominator - ); - - // -- Ensure rebates to distribute are within bounds -- - // Indexers can become under or over rebated if rebate parameters (alpha, lambda) - // change between successive collect calls for the same allocation - - // Ensure rebates to distribute are not negative (indexer is over-rebated) - queryRebates = MathUtils.diffOrZero(newRebates, alloc.distributedRebates); - - // Ensure rebates to distribute are not greater than available (indexer is under-rebated) - queryRebates = MathUtils.min(queryRebates, queryFees); - - // -- Burn rebates remanent -- - _graphToken().burnTokens(queryFees - queryRebates); - - // -- Distribute rebates -- - if (queryRebates > 0) { - alloc.distributedRebates = alloc.distributedRebates + queryRebates; - - // -- Collect delegation rewards into the delegation pool -- - delegationRewards = _collectDelegationQueryRewards(alloc.indexer, queryRebates); - queryRebates = queryRebates - delegationRewards; - - // -- Transfer or restake rebates -- - _sendRewards(queryRebates, alloc.indexer, __DEPRECATED_rewardsDestination[alloc.indexer] == address(0)); - } - } - - emit RebateCollected( - msg.sender, - alloc.indexer, - subgraphDeploymentID, - allocationID, - _graphEpochManager().currentEpoch(), - tokens, - protocolTax, - curationFees, - queryFees, - queryRebates, - delegationRewards - ); - } - - /** - * @notice Return if allocationID is used. - * @dev TODO: Remove after Horizon transition period - * @param allocationID Address used as signer by the indexer for an allocation - * @return True if allocationID already used - */ - function isAllocation(address allocationID) external view override returns (bool) { - return _getAllocationState(allocationID) != AllocationState.Null; - } - - /** - * @notice Return the allocation by ID. - * @dev TODO: Remove after Horizon transition period - * @param allocationID Address used as allocation identifier - * @return Allocation data - */ - function getAllocation(address allocationID) external view override returns (Allocation memory) { - return __DEPRECATED_allocations[allocationID]; - } - - /** - * @notice Return allocation data by ID. - * @dev To be called by the Rewards Manager to calculate rewards issuance. - * @dev TODO: Remove after Horizon transition period - * @param allocationID Address used as allocation identifier - * @return Allocation data - */ - function getAllocationData( - address allocationID - ) external view override returns (address, bytes32, uint256, uint256) { - Allocation memory allo = __DEPRECATED_allocations[allocationID]; - return (allo.indexer, allo.subgraphDeploymentID, allo.tokens, allo.accRewardsPerAllocatedToken); - } - - /** - * @notice Return the current state of an allocation - * @dev TODO: Remove after Horizon transition period - * @param allocationID Allocation identifier - * @return AllocationState enum with the state of the allocation - */ - 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 - */ - function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view override returns (uint256) { - return __DEPRECATED_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 - */ - function getIndexerStakedTokens(address indexer) external view override returns (uint256) { - return _serviceProviders[indexer].tokensStaked; - } - - /** - * @notice Getter that returns if an indexer has any stake. - * @param indexer Address of the indexer - * @return True if indexer has staked tokens - */ - function hasStake(address indexer) external view override returns (bool) { - return _serviceProviders[indexer].tokensStaked > 0; - } - - /** - * @notice (Legacy) Return true if operator is allowed for the service provider on the subgraph data service. - * @dev TODO: Delete after the transition period - * @param operator Address of the operator - * @param serviceProvider Address of the service provider - * @return True if operator is allowed for indexer, false otherwise - */ - function isOperator(address operator, address serviceProvider) public view override returns (bool) { - return _legacyOperatorAuth[serviceProvider][operator]; - } - - /** - * @dev Stake tokens on the service provider. - * TODO: Move to HorizonStaking after the transition period - * @param _serviceProvider Address of staking party - * @param _tokens Amount of tokens to stake - */ - function _stake(address _serviceProvider, uint256 _tokens) internal { - // Deposit tokens into the indexer stake - _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; - - emit StakeDeposited(_serviceProvider, _tokens); - } - - /** - * @dev Collect tax to burn for an amount of tokens. - * @param _tokens Total tokens received used to calculate the amount of tax to collect - * @param _percentage Percentage of tokens to burn as tax - * @return Amount of tax charged - */ - function _collectTax(uint256 _tokens, uint256 _percentage) private returns (uint256) { - uint256 tax = _tokens.mulPPMRoundUp(_percentage); - _graphToken().burnTokens(tax); // Burn tax if any - return tax; - } - - /** - * @dev 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 - */ - function _updateRewards(bytes32 _subgraphDeploymentID) private returns (uint256) { - return _graphRewardsManager().onSubgraphAllocationUpdate(_subgraphDeploymentID); - } - - /** - * @dev Assign rewards for the closed allocation to indexer and delegators. - * @param _allocationID Allocation - * @param _indexer Address of the indexer that did the allocation - */ - function _distributeRewards(address _allocationID, address _indexer) private { - // Automatically triggers update of rewards snapshot as allocation will change - // after this call. Take rewards mint tokens for the Staking contract to distribute - // between indexer and delegators - uint256 totalRewards = _graphRewardsManager().takeRewards(_allocationID); - if (totalRewards == 0) { - return; - } - - // Calculate delegation rewards and add them to the delegation pool - uint256 delegationRewards = _collectDelegationIndexingRewards(_indexer, totalRewards); - uint256 indexerRewards = totalRewards - delegationRewards; - - // Send the indexer rewards - _sendRewards(indexerRewards, _indexer, __DEPRECATED_rewardsDestination[_indexer] == address(0)); - } - - /** - * @dev Send rewards to the appropriate destination. - * @param _tokens Number of rewards tokens - * @param _beneficiary Address of the beneficiary of rewards - * @param _restake Whether to restake or not - */ - function _sendRewards(uint256 _tokens, address _beneficiary, bool _restake) private { - if (_tokens == 0) return; - - if (_restake) { - // Restake to place fees into the indexer stake - _stake(_beneficiary, _tokens); - } else { - // Transfer funds to the beneficiary's designated rewards destination if set - address destination = __DEPRECATED_rewardsDestination[_beneficiary]; - _graphToken().pushTokens(destination == address(0) ? _beneficiary : destination, _tokens); - } - } - - /** - * @dev Close an allocation and free the staked tokens. - * @param _allocationID The allocation identifier - * @param _poi Proof of indexing submitted for the allocated period - */ - function _closeAllocation(address _allocationID, bytes32 _poi) private { - // Allocation must exist and be active - AllocationState allocState = _getAllocationState(_allocationID); - require(allocState == AllocationState.Active, "!active"); - - // Get allocation - Allocation memory alloc = __DEPRECATED_allocations[_allocationID]; - - // Validate that an allocation cannot be closed before one epoch - alloc.closedAtEpoch = _graphEpochManager().currentEpoch(); - uint256 epochs = MathUtils.diffOrZero(alloc.closedAtEpoch, alloc.createdAtEpoch); - - // Indexer or operator can close an allocation - // Anyone is allowed to close ONLY under two concurrent conditions - // - After maxAllocationEpochs passed - // - When the allocation is for non-zero amount of tokens - bool isIndexer = isOperator(alloc.indexer, SUBGRAPH_DATA_SERVICE_ADDRESS); - if (epochs <= __DEPRECATED_maxAllocationEpochs || alloc.tokens == 0) { - require(isIndexer, "!auth"); - } - - // Close the allocation - __DEPRECATED_allocations[_allocationID].closedAtEpoch = alloc.closedAtEpoch; - - // -- Rewards Distribution -- - - // Process non-zero-allocation rewards tracking - if (alloc.tokens > 0) { - // Distribute rewards if proof of indexing was presented by the indexer or operator - if (isIndexer && _poi != 0) { - _distributeRewards(_allocationID, alloc.indexer); - } else { - _updateRewards(alloc.subgraphDeploymentID); - } - - // Free allocated tokens from use - _serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated = - _serviceProviders[alloc.indexer].__DEPRECATED_tokensAllocated - - alloc.tokens; - - // Track total allocations per subgraph - // Used for rewards calculations - __DEPRECATED_subgraphAllocations[alloc.subgraphDeploymentID] = - __DEPRECATED_subgraphAllocations[alloc.subgraphDeploymentID] - - alloc.tokens; - } - - emit AllocationClosed( - alloc.indexer, - alloc.subgraphDeploymentID, - alloc.closedAtEpoch, - alloc.tokens, - _allocationID, - msg.sender, - _poi, - !isIndexer - ); - } - - /** - * @dev 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 - * @return Amount of delegation rewards - */ - function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { - uint256 delegationRewards = 0; - IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; - if (pool.tokens > 0 && uint256(pool.__DEPRECATED_queryFeeCut).isValidPPM()) { - uint256 indexerCut = uint256(pool.__DEPRECATED_queryFeeCut).mulPPM(_tokens); - delegationRewards = _tokens - indexerCut; - pool.tokens = pool.tokens + delegationRewards; - } - return delegationRewards; - } - - /** - * @dev 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 - * @return Amount of delegation rewards - */ - function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { - uint256 delegationRewards = 0; - IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; - if (pool.tokens > 0 && uint256(pool.__DEPRECATED_indexingRewardCut).isValidPPM()) { - uint256 indexerCut = uint256(pool.__DEPRECATED_indexingRewardCut).mulPPM(_tokens); - delegationRewards = _tokens - indexerCut; - pool.tokens = pool.tokens + delegationRewards; - } - return delegationRewards; - } - - /** - * @dev Collect the curation fees for a subgraph deployment from an amount of tokens. - * This function transfer curation fees to the Curation contract by calling Curation.collect - * @param _subgraphDeploymentID Subgraph deployment to which the curation fees are related - * @param _tokens Total tokens received used to calculate the amount of fees to collect - * @param _curationCut Percentage of tokens to collect as fees - * @return Amount of curation fees - */ - function _collectCurationFees( - bytes32 _subgraphDeploymentID, - uint256 _tokens, - uint256 _curationCut - ) private returns (uint256) { - if (_tokens == 0) { - return 0; - } - - ICuration curation = _graphCuration(); - bool isCurationEnabled = _curationCut > 0 && address(curation) != address(0); - - if (isCurationEnabled && curation.isCurated(_subgraphDeploymentID)) { - uint256 curationFees = _tokens.mulPPMRoundUp(_curationCut); - if (curationFees > 0) { - // Transfer and call collect() - // This function transfer tokens to a trusted protocol contracts - // Then we call collect() to do the transfer bookeeping - _graphRewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); - _graphToken().pushTokens(address(curation), curationFees); - curation.collect(_subgraphDeploymentID, curationFees); - } - return curationFees; - } - return 0; - } - - /** - * @dev Return the current state of an allocation - * @param _allocationID Allocation identifier - * @return AllocationState enum with the state of the allocation - */ - function _getAllocationState(address _allocationID) private view returns (AllocationState) { - Allocation storage alloc = __DEPRECATED_allocations[_allocationID]; - - if (alloc.indexer == address(0)) { - return AllocationState.Null; - } - - if (alloc.createdAtEpoch != 0 && alloc.closedAtEpoch == 0) { - return AllocationState.Active; - } - - return AllocationState.Closed; - } -} diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index f4efae525..4e35d3b4e 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -1,6 +1,7 @@ // import '@nomicfoundation/hardhat-foundry' import '@nomicfoundation/hardhat-toolbox' import 'hardhat-storage-layout' +import 'hardhat-contract-sizer' import { HardhatUserConfig } from 'hardhat/config' diff --git a/packages/horizon/package.json b/packages/horizon/package.json index cdcfa441b..00c266f49 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -31,6 +31,7 @@ "eslint-graph-config": "workspace:^0.0.1", "ethers": "^6.4.0", "hardhat": "^2.20.1", + "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.8", "hardhat-storage-layout": "^0.1.7", "lint-staged": "^15.2.2", diff --git a/yarn.lock b/yarn.lock index 6d884fac8..98c24bbfa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2932,6 +2932,7 @@ __metadata: eslint-graph-config: "workspace:^0.0.1" ethers: "npm:^6.4.0" hardhat: "npm:^2.20.1" + hardhat-contract-sizer: "npm:^2.10.0" hardhat-gas-reporter: "npm:^1.0.8" hardhat-storage-layout: "npm:^0.1.7" lint-staged: "npm:^15.2.2" From aa9e908d8b42f51327cbc6207c339981e9be108b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 12:32:22 -0300 Subject: [PATCH 061/277] chore: rework interface directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 2 +- .../data-service/extensions/DataServiceFees.sol | 2 +- .../extensions/DataServiceFeesStorage.sol | 2 +- .../extensions/DataServicePausable.sol | 2 +- .../extensions/DataServiceRescuable.sol | 2 +- .../interfaces/IDataService.sol | 2 +- .../IDataServiceFees.sol | 2 +- .../IDataServicePausable.sol | 2 +- .../IDataServiceRescuable.sol | 2 +- .../contracts/interfaces/IHorizonStaking.sol | 6 +++--- .../{ => internal}/IHorizonStakingBase.sol | 2 +- .../{ => internal}/IHorizonStakingExtension.sol | 0 .../{ => internal}/IHorizonStakingMain.sol | 2 +- .../{ => internal}/IHorizonStakingTypes.sol | 0 .../horizon/contracts/staking/HorizonStaking.sol | 4 ++-- .../contracts/staking/HorizonStakingBase.sol | 16 ++++++++-------- .../staking/HorizonStakingExtension.sol | 4 ++-- .../contracts/staking/HorizonStakingStorage.sol | 4 ++-- 18 files changed, 28 insertions(+), 28 deletions(-) rename packages/horizon/contracts/{ => data-service}/interfaces/IDataService.sol (98%) rename packages/horizon/contracts/data-service/{extensions => interfaces}/IDataServiceFees.sol (91%) rename packages/horizon/contracts/data-service/{extensions => interfaces}/IDataServicePausable.sol (73%) rename packages/horizon/contracts/data-service/{extensions => interfaces}/IDataServiceRescuable.sol (79%) rename packages/horizon/contracts/interfaces/{ => internal}/IHorizonStakingBase.sol (97%) rename packages/horizon/contracts/interfaces/{ => internal}/IHorizonStakingExtension.sol (100%) rename packages/horizon/contracts/interfaces/{ => internal}/IHorizonStakingMain.sol (99%) rename packages/horizon/contracts/interfaces/{ => internal}/IHorizonStakingTypes.sol (100%) diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index 79e62216f..b2c39b6b0 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataService } from "../interfaces/IDataService.sol"; +import { IDataService } from "./interfaces/IDataService.sol"; import { DataServiceV1Storage } from "./DataServiceStorage.sol"; import { GraphDirectory } from "./GraphDirectory.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index b61526cf7..e25057f80 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataServiceFees } from "./IDataServiceFees.sol"; +import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; import { ProvisionTracker } from "../libraries/ProvisionTracker.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index a55a393e3..7069b9bb6 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataServiceFees } from "./IDataServiceFees.sol"; +import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; abstract contract DataServiceFeesV1Storage { diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index dc35d5f8a..d38b1fc0e 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataServicePausable } from "./IDataServicePausable.sol"; +import { IDataServicePausable } from "../interfaces/IDataServicePausable.sol"; import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; import { DataService } from "../DataService.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index fd790dae3..dffd76804 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { IDataServiceRescuable } from "./IDataServiceRescuable.sol"; +import { IDataServiceRescuable } from "../interfaces/IDataServiceRescuable.sol"; import { DataService } from "../DataService.sol"; diff --git a/packages/horizon/contracts/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol similarity index 98% rename from packages/horizon/contracts/interfaces/IDataService.sol rename to packages/horizon/contracts/data-service/interfaces/IDataService.sol index 7b401e533..3406c7029 100644 --- a/packages/horizon/contracts/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IGraphPayments } from "./IGraphPayments.sol"; +import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; /** * @title Interface of the base {DataService} contract as defined by the Graph Horizon specification. diff --git a/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol similarity index 91% rename from packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol rename to packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index 58f9f876f..b89ef5f5e 100644 --- a/packages/horizon/contracts/data-service/extensions/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataService } from "../../interfaces/IDataService.sol"; +import { IDataService } from "./IDataService.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; interface IDataServiceFees is IDataService { diff --git a/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol similarity index 73% rename from packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol rename to packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol index 6996c2bcf..04e17422d 100644 --- a/packages/horizon/contracts/data-service/extensions/IDataServicePausable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataService } from "../../interfaces/IDataService.sol"; +import { IDataService } from "./IDataService.sol"; interface IDataServicePausable is IDataService { function pause() external; diff --git a/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol similarity index 79% rename from packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol rename to packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index e8075dab5..76c5a53b6 100644 --- a/packages/horizon/contracts/data-service/extensions/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataService } from "../../interfaces/IDataService.sol"; +import { IDataService } from "./IDataService.sol"; interface IDataServiceRescuable is IDataService { function rescueGRT(address to, uint256 tokens) external; diff --git a/packages/horizon/contracts/interfaces/IHorizonStaking.sol b/packages/horizon/contracts/interfaces/IHorizonStaking.sol index 96560f7a3..13d9f19f6 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStaking.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStaking.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.24; -import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; -import { IHorizonStakingMain } from "./IHorizonStakingMain.sol"; -import { IHorizonStakingExtension } from "./IHorizonStakingExtension.sol"; +import { IHorizonStakingTypes } from "./internal/IHorizonStakingTypes.sol"; +import { IHorizonStakingMain } from "./internal/IHorizonStakingMain.sol"; +import { IHorizonStakingExtension } from "./internal/IHorizonStakingExtension.sol"; interface IHorizonStaking is IHorizonStakingTypes, IHorizonStakingMain, IHorizonStakingExtension {} diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol similarity index 97% rename from packages/horizon/contracts/interfaces/IHorizonStakingBase.sol rename to packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index a5f6e4fa4..2483ebda4 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; -import { IGraphPayments } from "./IGraphPayments.sol"; +import { IGraphPayments } from "../IGraphPayments.sol"; interface IHorizonStakingBase { /** diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol similarity index 100% rename from packages/horizon/contracts/interfaces/IHorizonStakingExtension.sol rename to packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol similarity index 99% rename from packages/horizon/contracts/interfaces/IHorizonStakingMain.sol rename to packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 8146ed5cb..7961902ec 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; -import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; interface IHorizonStakingMain is IHorizonStakingBase { /** diff --git a/packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol similarity index 100% rename from packages/horizon/contracts/interfaces/IHorizonStakingTypes.sol rename to packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index c780c3880..aeaffec2c 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -3,9 +3,9 @@ pragma solidity 0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; -import { IHorizonStakingMain } from "../interfaces/IHorizonStakingMain.sol"; +import { IHorizonStakingMain } from "../interfaces/internal/IHorizonStakingMain.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; -import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; +import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index cd54932b8..74b720679 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.24; -import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; -import { IHorizonStakingBase } from "../interfaces/IHorizonStakingBase.sol"; +import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; +import { IHorizonStakingBase } from "../interfaces/internal/IHorizonStakingBase.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; @@ -187,14 +187,14 @@ abstract contract HorizonStakingBase is return pool; } - function etIdleStake(address serviceProvider) public view returns (uint256 tokens) { + function _getIdleStake(address _serviceProvider) public view returns (uint256 tokens) { return - _serviceProviders[serviceProvider].tokensStaked - - _serviceProviders[serviceProvider].tokensProvisioned - - _serviceProviders[serviceProvider].__DEPRECATED_tokensLocked; + _serviceProviders[_serviceProvider].tokensStaked - + _serviceProviders[_serviceProvider].tokensProvisioned - + _serviceProviders[_serviceProvider].__DEPRECATED_tokensLocked; } - function gtProviderTokensAvailable(address serviceProvider, address verifier) public view returns (uint256) { - return _provisions[serviceProvider][verifier].tokens - _provisions[serviceProvider][verifier].tokensThawing; + function _getProviderTokensAvailable(address _serviceProvider, address _verifier) public view returns (uint256) { + return _provisions[_serviceProvider][_verifier].tokens - _provisions[_serviceProvider][_verifier].tokensThawing; } } diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 71cfd3dc6..a9666a832 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -5,8 +5,8 @@ pragma solidity 0.8.24; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; -import { IHorizonStakingExtension } from "../interfaces/IHorizonStakingExtension.sol"; -import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; +import { IHorizonStakingExtension } from "../interfaces/internal/IHorizonStakingExtension.sol"; +import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 96af3a4fb..ff9a1e2bb 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.24; -import { IHorizonStakingExtension } from "../interfaces/IHorizonStakingExtension.sol"; -import { IHorizonStakingTypes } from "../interfaces/IHorizonStakingTypes.sol"; +import { IHorizonStakingExtension } from "../interfaces/internal/IHorizonStakingExtension.sol"; +import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; // TODO: create custom var-name-mixedcase From ca633f40a469768880fbb22a34c90ce26f6f335f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 12:32:57 -0300 Subject: [PATCH 062/277] chore: disable autofix for solhint plugin, its bugged MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/solhint-plugin-graph/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solhint-plugin-graph/index.js b/packages/solhint-plugin-graph/index.js index d21c8840d..b2d3b88f6 100644 --- a/packages/solhint-plugin-graph/index.js +++ b/packages/solhint-plugin-graph/index.js @@ -112,7 +112,7 @@ module.exports = [ this.error( node, `'${name}' ${shouldHaveLeadingUnderscore ? 'should' : 'should not'} start with _`, - this.fixStatement(node, shouldHaveLeadingUnderscore, type) + // this.fixStatement(node, shouldHaveLeadingUnderscore, type) ) } }, From eef74f642b7cc9385d853e3e682b38de0b2fa288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 13:02:57 -0300 Subject: [PATCH 063/277] chore: order staking functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../internal/IHorizonStakingMain.sol | 30 +- .../contracts/staking/HorizonStaking.sol | 816 ++++++++++-------- .../contracts/staking/HorizonStakingBase.sol | 16 +- .../staking/HorizonStakingExtension.sol | 2 - 4 files changed, 474 insertions(+), 390 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 7961902ec..80613c018 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.24; import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; -import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; interface IHorizonStakingMain is IHorizonStakingBase { @@ -120,6 +119,19 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 feeCut ); + error HorizonStakingInvalidVerifier(address verifier); + error HorizonStakingVerifierAlreadyAllowed(address verifier); + error HorizonStakingVerifierNotAllowed(address verifier); + error HorizonStakingInvalidZeroTokens(); + error HorizonStakingInvalidProvision(address serviceProvider, address verifier); + error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); + error HorizonStakingInsufficientCapacity(); + error HorizonStakingInsufficientShares(); + error HorizonStakingInsufficientCapacityForLegacyAllocations(); + error HorizonStakingTooManyThawRequests(); + error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); + error HorizonStakingSlippageProtection(uint256 minExpectedShares, uint256 actualShares); + // deposit stake function stake(uint256 tokens) external; @@ -224,14 +236,6 @@ interface IHorizonStakingMain is IHorizonStakingBase { function acceptProvisionParameters(address serviceProvider) external; - /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param operator The address to check for auth - * @param serviceProvider The service provider on behalf of whom they're claiming to act - * @param verifier The verifier / data service on which they're claiming to act - */ - function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); - /** * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. * @param operator Address to authorize or unauthorize @@ -249,4 +253,12 @@ interface IHorizonStakingMain is IHorizonStakingBase { IGraphPayments.PaymentTypes paymentType, uint256 feeCut ) external; + + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param operator The address to check for auth + * @param serviceProvider The service provider on behalf of whom they're claiming to act + * @param verifier The verifier / data service on which they're claiming to act + */ + function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index aeaffec2c..67cfdf0b0 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -5,7 +5,6 @@ pragma solidity 0.8.24; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingMain } from "../interfaces/internal/IHorizonStakingMain.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; -import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; @@ -45,19 +44,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address private immutable STAKING_EXTENSION_ADDRESS; - error HorizonStakingInvalidVerifier(address verifier); - error HorizonStakingVerifierAlreadyAllowed(address verifier); - error HorizonStakingVerifierNotAllowed(address verifier); - error HorizonStakingInvalidZeroTokens(); - error HorizonStakingInvalidProvision(address serviceProvider, address verifier); - error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); - error HorizonStakingInsufficientCapacity(); - error HorizonStakingInsufficientShares(); - error HorizonStakingInsufficientCapacityForLegacyAllocations(); - error HorizonStakingTooManyThawRequests(); - error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); - error HorizonStakingSlippageProtection(uint256 minExpectedShares, uint256 actualShares); - modifier onlyAuthorized(address serviceProvider, address verifier) { if (!isAuthorized(msg.sender, serviceProvider, verifier)) { revert HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier); @@ -108,66 +94,25 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } } + /* + * STAKING + */ + /** * @notice Deposit tokens on the caller's stake. * @param tokens Amount of tokens to stake */ function stake(uint256 tokens) external override { - stakeTo(msg.sender, tokens); + _stakeTo(msg.sender, tokens); } /** - * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. - * @param operator Address to authorize or unauthorize - * @param verifier The verifier / data service on which they'll be allowed to operate - * @param allowed Whether the operator is authorized or not + * @notice Deposit tokens on the service provider stake, on behalf of the service provider. + * @param serviceProvider Address of the service provider + * @param tokens Amount of tokens to stake */ - function setOperator(address operator, address verifier, bool allowed) external override { - require(operator != msg.sender, "operator == sender"); - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - _legacyOperatorAuth[msg.sender][operator] = allowed; - } else { - _operatorAuth[msg.sender][verifier][operator] = allowed; - } - emit OperatorSet(msg.sender, operator, verifier, allowed); - } - - // for vesting contracts - function setOperatorLocked(address operator, address verifier, bool allowed) external override { - require(operator != msg.sender, "operator == sender"); - require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); - _operatorAuth[msg.sender][verifier][operator] = allowed; - emit OperatorSet(msg.sender, operator, verifier, allowed); - } - - function setDelegationFeeCut( - address serviceProvider, - address verifier, - IGraphPayments.PaymentTypes paymentType, - uint256 feeCut - ) external override { - delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; - emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); - } - - function setProvisionParameters( - address serviceProvider, - address verifier, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { - Provision storage prov = _provisions[serviceProvider][verifier]; - prov.maxVerifierCutPending = maxVerifierCut; - prov.thawingPeriodPending = thawingPeriod; - emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); - } - - function acceptProvisionParameters(address serviceProvider) external override notPartialPaused { - address verifier = msg.sender; - Provision storage prov = _provisions[serviceProvider][verifier]; - prov.maxVerifierCut = prov.maxVerifierCutPending; - prov.thawingPeriod = prov.thawingPeriodPending; - emit ProvisionParametersSet(serviceProvider, verifier, prov.maxVerifierCut, prov.thawingPeriod); + function stakeTo(address serviceProvider, uint256 tokens) external override notPartialPaused { + _stakeTo(serviceProvider, tokens); } /** @@ -182,40 +127,37 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, uint256 tokens ) external override notPartialPaused { - stakeTo(serviceProvider, tokens); + _stakeTo(serviceProvider, tokens); _addToProvision(serviceProvider, verifier, tokens); } /** - * @notice Provision stake to a verifier. The tokens will be locked with a thawing period - * and will be slashable by the verifier. This is the main mechanism to provision stake to a data - * service, where the data service is the verifier. - * This function can be called by the service provider or by an operator authorized by the provider - * for this specific verifier. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) - * @param tokens The amount of tokens that will be locked and slashable - * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing - * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + * @notice Move idle stake back to the owner's account. + * If tokens were thawing they must be deprovisioned first. + * Stake is removed from the protocol. + * @param tokens Amount of tokens to unstake */ - function provision( - address serviceProvider, - address verifier, - uint256 tokens, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { - if (_getIdleStake(serviceProvider) < tokens) { - revert HorizonStakingInsufficientCapacity(); - } + function unstake(uint256 tokens) external override notPaused { + _unstake(tokens); + } - _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); + /** + * @notice Withdraw service provider tokens once the thawing period has passed. + * @dev This is only needed during the transition period while we still have + * a global lock. After that, unstake() will also withdraw. + */ + function withdraw() external override notPaused { + _withdraw(msg.sender); } + /* + * PROVISIONS + */ + /** - * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period + * @notice Provision stake to a verifier. The tokens will be locked with a thawing period * and will be slashable by the verifier. This is the main mechanism to provision stake to a data - * service, where the data service is the verifier. Only authorized verifiers can be used. + * service, where the data service is the verifier. * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. * @param serviceProvider The service provider address @@ -224,7 +166,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ - function provisionLocked( + function provision( address serviceProvider, address verifier, uint256 tokens, @@ -234,9 +176,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { if (_getIdleStake(serviceProvider) < tokens) { revert HorizonStakingInsufficientCapacity(); } - if (!_allowedLockedVerifiers[verifier]) { - revert HorizonStakingInvalidVerifier(verifier); - } + _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } @@ -341,93 +281,205 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _addToProvision(serviceProvider, newVerifier, tokens); } - /** - * @notice Move idle stake back to the owner's account. - * If tokens were thawing they must be deprovisioned first. - * Stake is removed from the protocol. - * @param tokens Amount of tokens to unstake + function setProvisionParameters( + address serviceProvider, + address verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + Provision storage prov = _provisions[serviceProvider][verifier]; + prov.maxVerifierCutPending = maxVerifierCut; + prov.thawingPeriodPending = thawingPeriod; + emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); + } + + function acceptProvisionParameters(address serviceProvider) external override notPartialPaused { + address verifier = msg.sender; + Provision storage prov = _provisions[serviceProvider][verifier]; + prov.maxVerifierCut = prov.maxVerifierCutPending; + prov.thawingPeriod = prov.thawingPeriodPending; + emit ProvisionParametersSet(serviceProvider, verifier, prov.maxVerifierCut, prov.thawingPeriod); + } + + /* + * DELEGATION */ - function unstake(uint256 tokens) external override notPaused { - address serviceProvider = msg.sender; - if (tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - if (_getIdleStake(serviceProvider) < tokens) { - revert HorizonStakingInsufficientCapacity(); - } - ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; - uint256 stakedTokens = sp.tokensStaked; - // Check that the service provider's stake minus the tokens to unstake is sufficient - // to cover existing allocations - // TODO this is only needed until legacy allocations are closed, - // so we should remove it after the transition period - if ((stakedTokens - tokens) < sp.__DEPRECATED_tokensAllocated) { - revert HorizonStakingInsufficientCapacityForLegacyAllocations(); - } + function delegate( + address serviceProvider, + address verifier, + uint256 tokens, + uint256 minSharesOut + ) external override notPartialPaused { + _graphToken().pullTokens(msg.sender, tokens); + _delegate(serviceProvider, verifier, tokens, minSharesOut); + } - // This is also only during the transition period: we need - // to ensure tokens stay locked after closing legacy allocations. - // After sufficient time (56 days?) we should remove the closeAllocation function - // and set the thawing period to 0. - uint256 lockingPeriod = __DEPRECATED_thawingPeriod; - if (lockingPeriod == 0) { - sp.tokensStaked = stakedTokens - tokens; - _graphToken().pushTokens(serviceProvider, tokens); - emit StakeWithdrawn(serviceProvider, tokens); - } else { - // Before locking more tokens, withdraw any unlocked ones if possible - if (sp.__DEPRECATED_tokensLockedUntil != 0 && block.number >= sp.__DEPRECATED_tokensLockedUntil) { - _withdraw(serviceProvider); - } - // TODO remove after the transition period - // Take into account period averaging for multiple unstake requests - if (sp.__DEPRECATED_tokensLocked > 0) { - lockingPeriod = MathUtils.weightedAverageRoundingUp( - MathUtils.diffOrZero(sp.__DEPRECATED_tokensLockedUntil, block.number), // Remaining thawing period - sp.__DEPRECATED_tokensLocked, // Weighted by remaining unstaked tokens - lockingPeriod, // Thawing period - tokens // Weighted by new tokens to unstake - ); + // undelegate tokens from a service provider + // the shares are burned and replaced with shares in the thawing pool + function undelegate(address serviceProvider, address verifier, uint256 shares) external override notPartialPaused { + _undelegate(serviceProvider, verifier, shares); + } + + function withdrawDelegated( + address serviceProvider, + address verifier, + address newServiceProvider, + uint256 minSharesForNewProvider + ) external override notPartialPaused { + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); + Delegation storage delegation = pool.delegators[msg.sender]; + uint256 thawedTokens = 0; + + uint256 sharesThawing = pool.sharesThawing; + uint256 tokensThawing = pool.tokensThawing; + require(delegation.nThawRequests > 0, "no thaw requests"); + bytes32 thawRequestId = delegation.firstThawRequestId; + while (thawRequestId != bytes32(0)) { + ThawRequest storage thawRequest = _thawRequests[thawRequestId]; + if (thawRequest.thawingUntil <= block.timestamp) { + uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; + tokensThawing = tokensThawing - tokens; + sharesThawing = sharesThawing - thawRequest.shares; + thawedTokens = thawedTokens + tokens; + delete _thawRequests[thawRequestId]; + delegation.firstThawRequestId = thawRequest.next; + delegation.nThawRequests -= 1; + if (delegation.nThawRequests == 0) { + delegation.lastThawRequestId = bytes32(0); + } + } else { + break; } + thawRequestId = thawRequest.next; + } - // Update balances - sp.__DEPRECATED_tokensLocked = sp.__DEPRECATED_tokensLocked + tokens; - sp.__DEPRECATED_tokensLockedUntil = block.number + lockingPeriod; - emit StakeLocked(serviceProvider, sp.__DEPRECATED_tokensLocked, sp.__DEPRECATED_tokensLockedUntil); + pool.tokens = pool.tokens - thawedTokens; + pool.sharesThawing = sharesThawing; + pool.tokensThawing = tokensThawing; + + if (newServiceProvider != address(0)) { + _delegate(newServiceProvider, verifier, thawedTokens, minSharesForNewProvider); + } else { + _graphToken().pushTokens(msg.sender, thawedTokens); } + emit DelegatedTokensWithdrawn(serviceProvider, verifier, msg.sender, thawedTokens); } /** - * @notice Slash a service provider. This can only be called by a verifier to which - * the provider has provisioned stake, and up to the amount of tokens they have provisioned. - * @dev If delegation slashing is disabled, and the amount of tokens is more than the - * provider's provisioned self-stake, the delegation slashing is skipped without reverting. - * @param serviceProvider The service provider to slash - * @param tokens The amount of tokens to slash - * @param tokensVerifier The amount of tokens to transfer instead of burning - * @param verifierDestination The address to transfer the verifier cut to + * @notice Add tokens to a delegation pool (without getting shares). + * Used by data services to pay delegation fees/rewards. + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to add to the delegation pool */ - function slash( + function addToDelegationPool( address serviceProvider, - uint256 tokens, - uint256 tokensVerifier, - address verifierDestination + address verifier, + uint256 tokens ) external override notPartialPaused { - address verifier = msg.sender; - Provision storage prov = _provisions[serviceProvider][verifier]; - if (prov.tokens < tokens) { - revert HorizonStakingInsufficientTokens(tokens, prov.tokens); + if (tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); } + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); + pool.tokens = pool.tokens + tokens; + emit TokensAddedToDelegationPool(serviceProvider, verifier, tokens); + } - uint256 tokensToSlash = tokens; - uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); - if (providerTokensSlashed > 0) { - require(prov.tokens.mulPPM(prov.maxVerifierCut) >= tokensVerifier, "verifier cut too high"); - if (tokensVerifier > 0) { - _graphToken().pushTokens(verifierDestination, tokensVerifier); - emit VerifierTokensSent(serviceProvider, verifier, verifierDestination, tokensVerifier); - } + function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { + delegationSlashingEnabled = enabled; + emit DelegationSlashingEnabled(enabled); + } + + function setDelegationFeeCut( + address serviceProvider, + address verifier, + IGraphPayments.PaymentTypes paymentType, + uint256 feeCut + ) external override { + delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; + emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); + } + + // For backwards compatibility, delegates to the subgraph data service + // (Note this one doesn't have splippage/rounding protection!) + function delegate(address serviceProvider, uint256 tokens) external { + _graphToken().pullTokens(msg.sender, tokens); + _delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); + } + + // For backwards compatibility, undelegates from the subgraph data service + function undelegate(address serviceProvider, uint256 shares) external { + _undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); + } + + // For backwards compatibility, withdraws delegated tokens from the subgraph data service + function withdrawDelegated(address serviceProvider, address newServiceProvider) external { + _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0); + } + + /* + * OPERATOR + */ + + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @param operator Address to authorize or unauthorize + * @param verifier The verifier / data service on which they'll be allowed to operate + * @param allowed Whether the operator is authorized or not + */ + function setOperator(address operator, address verifier, bool allowed) external override { + require(operator != msg.sender, "operator == sender"); + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + _legacyOperatorAuth[msg.sender][operator] = allowed; + } else { + _operatorAuth[msg.sender][verifier][operator] = allowed; + } + emit OperatorSet(msg.sender, operator, verifier, allowed); + } + + // for vesting contracts + function setOperatorLocked(address operator, address verifier, bool allowed) external override { + require(operator != msg.sender, "operator == sender"); + require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); + _operatorAuth[msg.sender][verifier][operator] = allowed; + emit OperatorSet(msg.sender, operator, verifier, allowed); + } + + /* + * SLASHING + */ + + /** + * @notice Slash a service provider. This can only be called by a verifier to which + * the provider has provisioned stake, and up to the amount of tokens they have provisioned. + * @dev If delegation slashing is disabled, and the amount of tokens is more than the + * provider's provisioned self-stake, the delegation slashing is skipped without reverting. + * @param serviceProvider The service provider to slash + * @param tokens The amount of tokens to slash + * @param tokensVerifier The amount of tokens to transfer instead of burning + * @param verifierDestination The address to transfer the verifier cut to + */ + function slash( + address serviceProvider, + uint256 tokens, + uint256 tokensVerifier, + address verifierDestination + ) external override notPartialPaused { + address verifier = msg.sender; + Provision storage prov = _provisions[serviceProvider][verifier]; + if (prov.tokens < tokens) { + revert HorizonStakingInsufficientTokens(tokens, prov.tokens); + } + + uint256 tokensToSlash = tokens; + uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); + if (providerTokensSlashed > 0) { + require(prov.tokens.mulPPM(prov.maxVerifierCut) >= tokensVerifier, "verifier cut too high"); + if (tokensVerifier > 0) { + _graphToken().pushTokens(verifierDestination, tokensVerifier); + emit VerifierTokensSent(serviceProvider, verifier, verifierDestination, tokensVerifier); + } _graphToken().burnTokens(providerTokensSlashed - tokensVerifier); uint256 provisionFractionSlashed = (providerTokensSlashed * FIXED_POINT_PRECISION) / prov.tokens; // TODO check for rounding issues @@ -462,59 +514,41 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } } - // For backwards compatibility, delegates to the subgraph data service - // (Note this one doesn't have splippage/rounding protection!) - function delegate(address serviceProvider, uint256 tokens) external { - delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); - } - - // For backwards compatibility, undelegates from the subgraph data service - function undelegate(address serviceProvider, uint256 shares) external { - undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); - } - - // For backwards compatibility, withdraws delegated tokens from the subgraph data service - function withdrawDelegated(address serviceProvider, address newServiceProvider) external { - withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0); - } - - function setAllowedLockedVerifier(address verifier, bool allowed) external onlyGovernor { - _allowedLockedVerifiers[verifier] = allowed; - emit AllowedLockedVerifierSet(verifier, allowed); - } - - /** - * @notice Withdraw service provider tokens once the thawing period has passed. - * @dev This is only needed during the transition period while we still have - * a global lock. After that, unstake() will also withdraw. + /* + * LOCKED VERIFIERS */ - function withdraw() external override notPaused { - _withdraw(msg.sender); - } /** - * @notice Add tokens to a delegation pool (without getting shares). - * Used by data services to pay delegation fees/rewards. + * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period + * and will be slashable by the verifier. This is the main mechanism to provision stake to a data + * service, where the data service is the verifier. Only authorized verifiers can be used. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - * @param tokens The amount of tokens to add to the delegation pool + * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param tokens The amount of tokens that will be locked and slashable + * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ - function addToDelegationPool( + function provisionLocked( address serviceProvider, address verifier, - uint256 tokens - ) external override notPartialPaused { - if (tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + if (_getIdleStake(serviceProvider) < tokens) { + revert HorizonStakingInsufficientCapacity(); } - DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); - pool.tokens = pool.tokens + tokens; - emit TokensAddedToDelegationPool(serviceProvider, verifier, tokens); + if (!_allowedLockedVerifiers[verifier]) { + revert HorizonStakingInvalidVerifier(verifier); + } + _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } - function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { - delegationSlashingEnabled = enabled; - emit DelegationSlashingEnabled(enabled); + function setAllowedLockedVerifier(address verifier, bool allowed) external onlyGovernor { + _allowedLockedVerifiers[verifier] = allowed; + emit AllowedLockedVerifierSet(verifier, allowed); } // To be called at the end of the transition period, to set the deprecated thawing period to 0 @@ -529,63 +563,224 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @notice Deposit tokens on the service provider stake, on behalf of the service provider. - * @param serviceProvider Address of the service provider - * @param tokens Amount of tokens to stake + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param operator The address to check for auth + * @param serviceProvider The service provider on behalf of whom they're claiming to act + * @param verifier The verifier / data service on which they're claiming to act */ - function stakeTo(address serviceProvider, uint256 tokens) public override notPartialPaused { - if (tokens == 0) { + function isAuthorized( + address operator, + address serviceProvider, + address verifier + ) public view override returns (bool) { + if (operator == serviceProvider) { + return true; + } + if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return _legacyOperatorAuth[serviceProvider][operator]; + } else { + return _operatorAuth[serviceProvider][verifier][operator]; + } + } + + /* + * PRIVATE FUNCTIONS + */ + function _stakeTo(address _serviceProvider, uint256 _tokens) private { + if (_tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } // Transfer tokens to stake from caller to this contract - _graphToken().pullTokens(msg.sender, tokens); + _graphToken().pullTokens(msg.sender, _tokens); // Stake the transferred tokens - _stake(serviceProvider, tokens); + _stake(_serviceProvider, _tokens); } - function delegate( - address serviceProvider, - address verifier, - uint256 tokens, - uint256 minSharesOut - ) public override notPartialPaused { - // Transfer tokens to stake from caller to this contract - _graphToken().pullTokens(msg.sender, tokens); - _delegate(serviceProvider, verifier, tokens, minSharesOut); + function _unstake(uint256 _tokens) private { + address serviceProvider = msg.sender; + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + if (_getIdleStake(serviceProvider) < _tokens) { + revert HorizonStakingInsufficientCapacity(); + } + + ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; + uint256 stakedTokens = sp.tokensStaked; + // Check that the service provider's stake minus the tokens to unstake is sufficient + // to cover existing allocations + // TODO this is only needed until legacy allocations are closed, + // so we should remove it after the transition period + if ((stakedTokens - _tokens) < sp.__DEPRECATED_tokensAllocated) { + revert HorizonStakingInsufficientCapacityForLegacyAllocations(); + } + + // This is also only during the transition period: we need + // to ensure tokens stay locked after closing legacy allocations. + // After sufficient time (56 days?) we should remove the closeAllocation function + // and set the thawing period to 0. + uint256 lockingPeriod = __DEPRECATED_thawingPeriod; + if (lockingPeriod == 0) { + sp.tokensStaked = stakedTokens - _tokens; + _graphToken().pushTokens(serviceProvider, _tokens); + emit StakeWithdrawn(serviceProvider, _tokens); + } else { + // Before locking more tokens, withdraw any unlocked ones if possible + if (sp.__DEPRECATED_tokensLockedUntil != 0 && block.number >= sp.__DEPRECATED_tokensLockedUntil) { + _withdraw(serviceProvider); + } + // TODO remove after the transition period + // Take into account period averaging for multiple unstake requests + if (sp.__DEPRECATED_tokensLocked > 0) { + lockingPeriod = MathUtils.weightedAverageRoundingUp( + MathUtils.diffOrZero(sp.__DEPRECATED_tokensLockedUntil, block.number), // Remaining thawing period + sp.__DEPRECATED_tokensLocked, // Weighted by remaining unstaked tokens + lockingPeriod, // Thawing period + _tokens // Weighted by new tokens to unstake + ); + } + + // Update balances + sp.__DEPRECATED_tokensLocked = sp.__DEPRECATED_tokensLocked + _tokens; + sp.__DEPRECATED_tokensLockedUntil = block.number + lockingPeriod; + emit StakeLocked(serviceProvider, sp.__DEPRECATED_tokensLocked, sp.__DEPRECATED_tokensLockedUntil); + } } - // undelegate tokens from a service provider - // the shares are burned and replaced with shares in the thawing pool - function undelegate(address serviceProvider, address verifier, uint256 shares) public override notPartialPaused { - require(shares > 0, "!shares"); - DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); + /** + * @dev Creates a provision + */ + function _createProvision( + address _serviceProvider, + uint256 _tokens, + address _verifier, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) private { + require(_tokens >= MIN_PROVISION_SIZE, "!tokens"); + require(_maxVerifierCut <= MAX_MAX_VERIFIER_CUT, "maxVerifierCut too high"); + require(_thawingPeriod <= _maxThawingPeriod, "thawingPeriod too high"); + _provisions[_serviceProvider][_verifier] = Provision({ + tokens: _tokens, + tokensThawing: 0, + sharesThawing: 0, + maxVerifierCut: _maxVerifierCut, + thawingPeriod: _thawingPeriod, + createdAt: uint64(block.timestamp), + firstThawRequestId: bytes32(0), + lastThawRequestId: bytes32(0), + nThawRequests: 0, + maxVerifierCutPending: _maxVerifierCut, + thawingPeriodPending: _thawingPeriod + }); + + ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; + sp.tokensProvisioned = sp.tokensProvisioned + _tokens; + + emit ProvisionCreated(_serviceProvider, _verifier, _tokens, _maxVerifierCut, _thawingPeriod); + } + + function _addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) private { + Provision storage prov = _provisions[_serviceProvider][_verifier]; + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + if (prov.createdAt == 0) { + revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); + } + if (_getIdleStake(_serviceProvider) < _tokens) { + revert HorizonStakingInsufficientCapacity(); + } + + prov.tokens = prov.tokens + _tokens; + _serviceProviders[_serviceProvider].tokensProvisioned = + _serviceProviders[_serviceProvider].tokensProvisioned + + _tokens; + emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); + } + + /** + * @dev Withdraw service provider tokens once the thawing period has passed. + * @param _serviceProvider Address of service provider to withdraw funds from + */ + function _withdraw(address _serviceProvider) private { + // Get tokens available for withdraw and update balance + ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; + uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; + require(tokensToWithdraw > 0, "!tokens"); + require(block.number >= sp.__DEPRECATED_tokensLockedUntil, "locked"); + + // Reset locked tokens + sp.__DEPRECATED_tokensLocked = 0; + sp.__DEPRECATED_tokensLockedUntil = 0; + + sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; + + // Return tokens to the service provider + _graphToken().pushTokens(_serviceProvider, tokensToWithdraw); + + emit StakeWithdrawn(_serviceProvider, tokensToWithdraw); + } + + function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) private { + if (_tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + // TODO: remove this after L2 transfer tool for delegation is removed + if (_tokens < MIN_DELEGATION) { + revert HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens); + } + if (_provisions[_serviceProvider][_verifier].tokens == 0) { + revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); + } + + DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); + Delegation storage delegation = pool.delegators[msg.sender]; + + // Calculate shares to issue + uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); + if (shares == 0 || shares < _minSharesOut) { + revert HorizonStakingSlippageProtection(_minSharesOut, shares); + } + + pool.tokens = pool.tokens + _tokens; + pool.shares = pool.shares + shares; + + delegation.shares = delegation.shares + shares; + + emit TokensDelegated(_serviceProvider, _verifier, msg.sender, _tokens); + } + + function _undelegate(address _serviceProvider, address _verifier, uint256 _shares) private { + require(_shares > 0, "!shares"); + DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); Delegation storage delegation = pool.delegators[msg.sender]; - require(delegation.shares >= shares, "!shares-avail"); + require(delegation.shares >= _shares, "!shares-avail"); - uint256 tokens = (shares * (pool.tokens - pool.tokensThawing)) / pool.shares; + uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); pool.tokensThawing = pool.tokensThawing + tokens; - pool.shares = pool.shares - shares; + pool.shares = pool.shares - _shares; pool.sharesThawing = pool.sharesThawing + thawingShares; - delegation.shares = delegation.shares - shares; + delegation.shares = delegation.shares - _shares; // TODO: remove this when L2 transfer tools are removed if (delegation.shares != 0) { uint256 remainingTokens = (delegation.shares * (pool.tokens - pool.tokensThawing)) / pool.shares; require(remainingTokens >= MIN_DELEGATION, "!minimum-delegation"); } bytes32 thawRequestId = keccak256( - abi.encodePacked(serviceProvider, verifier, msg.sender, delegation.nextThawRequestNonce) + abi.encodePacked(_serviceProvider, _verifier, msg.sender, delegation.nextThawRequestNonce) ); delegation.nextThawRequestNonce += 1; ThawRequest storage thawRequest = _thawRequests[thawRequestId]; thawRequest.shares = thawingShares; thawRequest.thawingUntil = uint64( - block.timestamp + uint256(_provisions[serviceProvider][verifier].thawingPeriod) + block.timestamp + uint256(_provisions[_serviceProvider][_verifier].thawingPeriod) ); require(delegation.nThawRequests < MAX_THAW_REQUESTS, "max thaw requests"); if (delegation.nThawRequests == 0) { @@ -597,16 +792,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { unchecked { delegation.nThawRequests += 1; } - emit TokensUndelegated(serviceProvider, verifier, msg.sender, tokens); + emit TokensUndelegated(_serviceProvider, _verifier, msg.sender, tokens); } - function withdrawDelegated( - address serviceProvider, - address verifier, - address newServiceProvider, - uint256 minSharesForNewProvider - ) public override notPartialPaused { - DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); + function _withdrawDelegated( + address _serviceProvider, + address _verifier, + address _newServiceProvider, + uint256 _minSharesForNewProvider + ) private { + DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); Delegation storage delegation = pool.delegators[msg.sender]; uint256 thawedTokens = 0; @@ -637,98 +832,15 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { pool.sharesThawing = sharesThawing; pool.tokensThawing = tokensThawing; - if (newServiceProvider != address(0)) { - _delegate(newServiceProvider, verifier, thawedTokens, minSharesForNewProvider); + if (_newServiceProvider != address(0)) { + _delegate(_newServiceProvider, _verifier, thawedTokens, _minSharesForNewProvider); } else { _graphToken().pushTokens(msg.sender, thawedTokens); } - emit DelegatedTokensWithdrawn(serviceProvider, verifier, msg.sender, thawedTokens); - } - - /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param operator The address to check for auth - * @param serviceProvider The service provider on behalf of whom they're claiming to act - * @param verifier The verifier / data service on which they're claiming to act - */ - function isAuthorized( - address operator, - address serviceProvider, - address verifier - ) public view override returns (bool) { - if (operator == serviceProvider) { - return true; - } - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - return _legacyOperatorAuth[serviceProvider][operator]; - } else { - return _operatorAuth[serviceProvider][verifier][operator]; - } - } - - function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) internal { - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - // TODO: remove this after L2 transfer tool for delegation is removed - if (_tokens < MIN_DELEGATION) { - revert HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens); - } - if (_provisions[_serviceProvider][_verifier].tokens == 0) { - revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); - } - - DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); - Delegation storage delegation = pool.delegators[msg.sender]; - - // Calculate shares to issue - uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); - if (shares == 0 || shares < _minSharesOut) { - revert HorizonStakingSlippageProtection(_minSharesOut, shares); - } - - pool.tokens = pool.tokens + _tokens; - pool.shares = pool.shares + shares; - - delegation.shares = delegation.shares + shares; - - emit TokensDelegated(_serviceProvider, _verifier, msg.sender, _tokens); - } - - /** - * @dev Creates a provision - */ - function _createProvision( - address _serviceProvider, - uint256 _tokens, - address _verifier, - uint32 _maxVerifierCut, - uint64 _thawingPeriod - ) internal { - require(_tokens >= MIN_PROVISION_SIZE, "!tokens"); - require(_maxVerifierCut <= MAX_MAX_VERIFIER_CUT, "maxVerifierCut too high"); - require(_thawingPeriod <= _maxThawingPeriod, "thawingPeriod too high"); - _provisions[_serviceProvider][_verifier] = Provision({ - tokens: _tokens, - tokensThawing: 0, - sharesThawing: 0, - maxVerifierCut: _maxVerifierCut, - thawingPeriod: _thawingPeriod, - createdAt: uint64(block.timestamp), - firstThawRequestId: bytes32(0), - lastThawRequestId: bytes32(0), - nThawRequests: 0, - maxVerifierCutPending: _maxVerifierCut, - thawingPeriodPending: _thawingPeriod - }); - - ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; - sp.tokensProvisioned = sp.tokensProvisioned + _tokens; - - emit ProvisionCreated(_serviceProvider, _verifier, _tokens, _maxVerifierCut, _thawingPeriod); + emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, thawedTokens); } - function _fulfillThawRequests(address _serviceProvider, address _verifier, uint256 _tokens) internal { + function _fulfillThawRequests(address _serviceProvider, address _verifier, uint256 _tokens) private { Provision storage prov = _provisions[_serviceProvider][_verifier]; uint256 tokensRemaining = _tokens; uint256 sharesThawing = prov.sharesThawing; @@ -768,46 +880,4 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { prov.tokens = prov.tokens - _tokens; _serviceProviders[_serviceProvider].tokensProvisioned -= _tokens; } - - function _addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) internal { - Provision storage prov = _provisions[_serviceProvider][_verifier]; - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - if (prov.createdAt == 0) { - revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); - } - if (_getIdleStake(_serviceProvider) < _tokens) { - revert HorizonStakingInsufficientCapacity(); - } - - prov.tokens = prov.tokens + _tokens; - _serviceProviders[_serviceProvider].tokensProvisioned = - _serviceProviders[_serviceProvider].tokensProvisioned + - _tokens; - emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); - } - - /** - * @dev Withdraw service provider tokens once the thawing period has passed. - * @param _serviceProvider Address of service provider to withdraw funds from - */ - function _withdraw(address _serviceProvider) private { - // Get tokens available for withdraw and update balance - ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; - uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; - require(tokensToWithdraw > 0, "!tokens"); - require(block.number >= sp.__DEPRECATED_tokensLockedUntil, "locked"); - - // Reset locked tokens - sp.__DEPRECATED_tokensLocked = 0; - sp.__DEPRECATED_tokensLockedUntil = 0; - - sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; - - // Return tokens to the service provider - _graphToken().pushTokens(_serviceProvider, tokensToWithdraw); - - emit StakeWithdrawn(_serviceProvider, tokensToWithdraw); - } } diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 74b720679..e392a992b 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -57,7 +57,7 @@ abstract contract HorizonStakingBase is uint256 providerThawingTokens = _provisions[serviceProvider][verifier].tokensThawing; uint256 tokensDelegatedMax = (providerTokens - providerThawingTokens) * (uint256(delegationRatio)); uint256 tokensDelegatedCapacity = MathUtils.min( - getDelegatedTokensAvailable(serviceProvider, verifier), + _getDelegatedTokensAvailable(serviceProvider, verifier), tokensDelegatedMax ); return providerTokens - providerThawingTokens + tokensDelegatedCapacity; @@ -119,9 +119,8 @@ abstract contract HorizonStakingBase is function getDelegatedTokensAvailable( address serviceProvider, address verifier - ) public view override returns (uint256) { - DelegationPoolInternal storage poolInternal = _getDelegationPool(serviceProvider, verifier); - return poolInternal.tokens - poolInternal.tokensThawing; + ) external view override returns (uint256) { + return _getDelegatedTokensAvailable(serviceProvider, verifier); } // staked tokens that are currently not provisioned, aka idle stake @@ -187,14 +186,19 @@ abstract contract HorizonStakingBase is return pool; } - function _getIdleStake(address _serviceProvider) public view returns (uint256 tokens) { + function _getIdleStake(address _serviceProvider) internal view returns (uint256 tokens) { return _serviceProviders[_serviceProvider].tokensStaked - _serviceProviders[_serviceProvider].tokensProvisioned - _serviceProviders[_serviceProvider].__DEPRECATED_tokensLocked; } - function _getProviderTokensAvailable(address _serviceProvider, address _verifier) public view returns (uint256) { + function _getProviderTokensAvailable(address _serviceProvider, address _verifier) internal view returns (uint256) { return _provisions[_serviceProvider][_verifier].tokens - _provisions[_serviceProvider][_verifier].tokensThawing; } + + function _getDelegatedTokensAvailable(address _serviceProvider, address _verifier) internal view returns (uint256) { + DelegationPoolInternal storage poolInternal = _getDelegationPool(_serviceProvider, _verifier); + return poolInternal.tokens - poolInternal.tokensThawing; + } } diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index a9666a832..ce53e2860 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -16,8 +16,6 @@ import { ExponentialRebates } from "./libraries/ExponentialRebates.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; import { HorizonStakingBase } from "./HorizonStakingBase.sol"; -import { Managed } from "./utilities/Managed.sol"; -import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; /** * @title Base Staking contract From 3ca420e2aff961eb730a722b7d74b39bcdcb1a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 13:53:58 -0300 Subject: [PATCH 064/277] chore: staking function ordering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/staking/HorizonStaking.sol | 138 ++++++++++-------- 1 file changed, 74 insertions(+), 64 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 67cfdf0b0..616efca8a 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -45,7 +45,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address private immutable STAKING_EXTENSION_ADDRESS; modifier onlyAuthorized(address serviceProvider, address verifier) { - if (!isAuthorized(msg.sender, serviceProvider, verifier)) { + if (!_isAuthorized(msg.sender, serviceProvider, verifier)) { revert HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier); } _; @@ -248,7 +248,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // moves thawed stake from a provision back into the provider's available stake function deprovision(address serviceProvider, address verifier, uint256 tokens) external override notPartialPaused { - require(isAuthorized(msg.sender, serviceProvider, verifier), "!auth"); + require(_isAuthorized(msg.sender, serviceProvider, verifier), "!auth"); if (tokens == 0) { revert HorizonStakingInvalidZeroTokens(); } @@ -315,6 +315,26 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _delegate(serviceProvider, verifier, tokens, minSharesOut); } + /** + * @notice Add tokens to a delegation pool (without getting shares). + * Used by data services to pay delegation fees/rewards. + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to add to the delegation pool + */ + function addToDelegationPool( + address serviceProvider, + address verifier, + uint256 tokens + ) external override notPartialPaused { + if (tokens == 0) { + revert HorizonStakingInvalidZeroTokens(); + } + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); + pool.tokens = pool.tokens + tokens; + emit TokensAddedToDelegationPool(serviceProvider, verifier, tokens); + } + // undelegate tokens from a service provider // the shares are burned and replaced with shares in the thawing pool function undelegate(address serviceProvider, address verifier, uint256 shares) external override notPartialPaused { @@ -366,31 +386,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit DelegatedTokensWithdrawn(serviceProvider, verifier, msg.sender, thawedTokens); } - /** - * @notice Add tokens to a delegation pool (without getting shares). - * Used by data services to pay delegation fees/rewards. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - * @param tokens The amount of tokens to add to the delegation pool - */ - function addToDelegationPool( - address serviceProvider, - address verifier, - uint256 tokens - ) external override notPartialPaused { - if (tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); - pool.tokens = pool.tokens + tokens; - emit TokensAddedToDelegationPool(serviceProvider, verifier, tokens); - } - - function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { - delegationSlashingEnabled = enabled; - emit DelegationSlashingEnabled(enabled); - } - function setDelegationFeeCut( address serviceProvider, address verifier, @@ -418,34 +413,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0); } - /* - * OPERATOR - */ - - /** - * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. - * @param operator Address to authorize or unauthorize - * @param verifier The verifier / data service on which they'll be allowed to operate - * @param allowed Whether the operator is authorized or not - */ - function setOperator(address operator, address verifier, bool allowed) external override { - require(operator != msg.sender, "operator == sender"); - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - _legacyOperatorAuth[msg.sender][operator] = allowed; - } else { - _operatorAuth[msg.sender][verifier][operator] = allowed; - } - emit OperatorSet(msg.sender, operator, verifier, allowed); - } - - // for vesting contracts - function setOperatorLocked(address operator, address verifier, bool allowed) external override { - require(operator != msg.sender, "operator == sender"); - require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); - _operatorAuth[msg.sender][verifier][operator] = allowed; - emit OperatorSet(msg.sender, operator, verifier, allowed); - } - /* * SLASHING */ @@ -546,11 +513,26 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } + // for vesting contracts + function setOperatorLocked(address operator, address verifier, bool allowed) external override { + require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); + _setOperator(operator, verifier, allowed); + } + + /* + * GOVERNANCE + */ + function setAllowedLockedVerifier(address verifier, bool allowed) external onlyGovernor { _allowedLockedVerifiers[verifier] = allowed; emit AllowedLockedVerifierSet(verifier, allowed); } + function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { + delegationSlashingEnabled = enabled; + emit DelegationSlashingEnabled(enabled); + } + // To be called at the end of the transition period, to set the deprecated thawing period to 0 function clearThawingPeriod() external onlyGovernor { __DEPRECATED_thawingPeriod = 0; @@ -562,6 +544,20 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit ParameterUpdated("maxThawingPeriod"); } + /* + * OPERATOR + */ + + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @param operator Address to authorize or unauthorize + * @param verifier The verifier / data service on which they'll be allowed to operate + * @param allowed Whether the operator is authorized or not + */ + function setOperator(address operator, address verifier, bool allowed) external override { + _setOperator(operator, verifier, allowed); + } + /** * @notice Check if an operator is authorized for the caller on a specific verifier / data service. * @param operator The address to check for auth @@ -572,15 +568,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address operator, address serviceProvider, address verifier - ) public view override returns (bool) { - if (operator == serviceProvider) { - return true; - } - if (verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - return _legacyOperatorAuth[serviceProvider][operator]; - } else { - return _operatorAuth[serviceProvider][verifier][operator]; - } + ) external view override returns (bool) { + return _isAuthorized(operator, serviceProvider, verifier); } /* @@ -840,6 +829,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, thawedTokens); } + function _setOperator(address _operator, address _verifier, bool _allowed) private { + require(_operator != msg.sender, "operator == sender"); + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + _legacyOperatorAuth[msg.sender][_operator] = _allowed; + } else { + _operatorAuth[msg.sender][_verifier][_operator] = _allowed; + } + emit OperatorSet(msg.sender, _operator, _verifier, _allowed); + } + function _fulfillThawRequests(address _serviceProvider, address _verifier, uint256 _tokens) private { Provision storage prov = _provisions[_serviceProvider][_verifier]; uint256 tokensRemaining = _tokens; @@ -880,4 +879,15 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { prov.tokens = prov.tokens - _tokens; _serviceProviders[_serviceProvider].tokensProvisioned -= _tokens; } + + function _isAuthorized(address _operator, address _serviceProvider, address _verifier) private view returns (bool) { + if (_operator == _serviceProvider) { + return true; + } + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { + return _legacyOperatorAuth[_serviceProvider][_operator]; + } else { + return _operatorAuth[_serviceProvider][_verifier][_operator]; + } + } } From 1f4db7049ef807876d41efb2d8b54dfebbe07d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 13:56:09 -0300 Subject: [PATCH 065/277] fix(ss): interface importsy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../subgraph-service/contracts/interfaces/ISubgraphService.sol | 2 +- packages/subgraph-service/test/mocks/MockHorizonStaking.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 52561fb74..0cf65f37f 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; -import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/extensions/IDataServiceFees.sol"; +import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataServiceFees.sol"; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index 13281fa6e..9efebeb60 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import "forge-std/Test.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; -import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStakingTypes.sol"; +import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol"; import { MockGRTToken } from "./MockGRTToken.sol"; contract MockHorizonStaking { From 511ef3031a72799c2e767a99aba90d556817c88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 14:22:19 -0300 Subject: [PATCH 066/277] chore: ensure events and errors consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServiceFees.sol | 15 --- .../extensions/DataServicePausable.sol | 4 - .../extensions/DataServiceRescuable.sol | 9 -- .../interfaces/IDataServiceFees.sol | 14 +++ .../interfaces/IDataServicePausable.sol | 5 + .../interfaces/IDataServiceRescuable.sol | 10 ++ .../contracts/interfaces/IGraphPayments.sol | 4 + .../contracts/interfaces/IPaymentsEscrow.sol | 29 ++++++ .../contracts/interfaces/ITAPCollector.sol | 13 +++ .../internal/IHorizonStakingExtension.sol | 6 +- .../internal/IHorizonStakingMain.sol | 8 +- .../contracts/payments/GraphPayments.sol | 7 -- .../contracts/payments/PaymentsEscrow.sol | 59 +++-------- .../payments/collectors/TAPCollector.sol | 13 --- .../contracts/staking/HorizonStaking.sol | 6 +- .../staking/HorizonStakingExtension.sol | 2 +- .../contracts/staking/utilities/Managed.sol | 5 - .../contracts/DisputeManager.sol | 98 ------------------- .../contracts/SubgraphService.sol | 15 +-- .../contracts/interfaces/IDisputeManager.sol | 98 +++++++++++++++++++ .../contracts/interfaces/ISubgraphService.sol | 14 +++ 21 files changed, 211 insertions(+), 223 deletions(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index e25057f80..4770ebc41 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -12,21 +12,6 @@ import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol"; abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDataServiceFees { using ProvisionTracker for mapping(address => uint256); - event StakeClaimLocked( - address indexed serviceProvider, - bytes32 indexed claimId, - uint256 tokens, - uint256 unlockTimestamp - ); - event StakeClaimReleased( - address indexed serviceProvider, - bytes32 indexed claimId, - uint256 tokens, - uint256 releaseAt - ); - - error DataServiceFeesClaimNotFound(bytes32 claimId); - function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external virtual { _releaseStake(feeType, msg.sender, n); } diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index d38b1fc0e..d1800ad38 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -9,10 +9,6 @@ import { DataService } from "../DataService.sol"; abstract contract DataServicePausable is Pausable, DataService, IDataServicePausable { mapping(address pauseGuardian => bool allowed) public pauseGuardians; - event PauseGuardianSet(address indexed account, bool allowed); - - error DataServicePausableNotPauseGuardian(address account); - modifier onlyPauseGuardian() { if (!pauseGuardians[msg.sender]) { revert DataServicePausableNotPauseGuardian(msg.sender); diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index dffd76804..8fff2947d 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -18,15 +18,6 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { mapping(address rescuer => bool allowed) public rescuers; - /** - * @dev Tokens rescued by the user - */ - event TokensRescued(address indexed from, address indexed to, uint256 tokens); - event RescuerSet(address indexed account, bool allowed); - - error DataServiceRescuableCannotRescueZero(); - error DataServiceRescuableNotRescuer(address account); - modifier onlyRescuer() { if (!rescuers[msg.sender]) { revert DataServiceRescuableNotRescuer(msg.sender); diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index b89ef5f5e..b5d5d88d5 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -23,5 +23,19 @@ interface IDataServiceFees is IDataService { bytes32 nextClaim; } + event StakeClaimLocked( + address indexed serviceProvider, + bytes32 indexed claimId, + uint256 tokens, + uint256 unlockTimestamp + ); + event StakeClaimReleased( + address indexed serviceProvider, + bytes32 indexed claimId, + uint256 tokens, + uint256 releaseAt + ); + error DataServiceFeesClaimNotFound(bytes32 claimId); + function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external; } diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol index 04e17422d..2c89ca860 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol @@ -4,6 +4,11 @@ pragma solidity 0.8.24; import { IDataService } from "./IDataService.sol"; interface IDataServicePausable is IDataService { + event PauseGuardianSet(address indexed account, bool allowed); + + error DataServicePausableNotPauseGuardian(address account); + function pause() external; + function unpause() external; } diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index 76c5a53b6..4762fd349 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -4,6 +4,16 @@ pragma solidity 0.8.24; import { IDataService } from "./IDataService.sol"; interface IDataServiceRescuable is IDataService { + /** + * @dev Tokens rescued by the user + */ + event TokensRescued(address indexed from, address indexed to, uint256 tokens); + event RescuerSet(address indexed account, bool allowed); + + error DataServiceRescuableCannotRescueZero(); + error DataServiceRescuableNotRescuer(address account); + function rescueGRT(address to, uint256 tokens) external; + function rescueETH(address payable to, uint256 tokens) external; } diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index bb0274b2d..9002185c6 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -9,6 +9,10 @@ interface IGraphPayments { IndexingRewards } + // -- Errors -- + + error GraphPaymentsInsufficientTokens(uint256 available, uint256 required); + // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( PaymentTypes paymentType, diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 20b10491f..db5c56218 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -17,6 +17,35 @@ interface IPaymentsEscrow { uint256 thawEndTimestamp; } + // -- Events -- + + event AuthorizedCollector(address indexed payer, address indexed dataService); + event ThawCollector(address indexed payer, address indexed dataService); + event CancelThawCollector(address indexed payer, address indexed dataService); + event RevokeCollector(address indexed payer, address indexed dataService); + event Deposit(address indexed payer, address indexed receiver, uint256 tokens); + event CancelThaw(address indexed payer, address indexed receiver); + event Thaw( + address indexed payer, + address indexed receiver, + uint256 tokens, + uint256 totalTokensThawing, + uint256 thawEndTimestamp + ); + event Withdraw(address indexed payer, address indexed receiver, uint256 tokens); + event EscrowCollected(address indexed payer, address indexed receiver, uint256 tokens); + + // -- Errors -- + + error PaymentsEscrowInsufficientTokensThawing(); + error PaymentsEscrowInsufficientBalance(uint256 available, uint256 required); + error PaymentsEscrowNotThawing(); + error PaymentsEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); + error PaymentsEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); + error PaymentsEscrowCollectorNotAuthorized(address sender, address dataService); + error PaymentsEscrowInsufficientAllowance(uint256 available, uint256 required); + error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); + // Deposit funds into the escrow for a receiver function deposit(address receiver, uint256 tokens) external; diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 90b2c53dd..50db686c9 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.24; +import { IGraphPayments } from "./IGraphPayments.sol"; import { IPaymentsCollector } from "./IPaymentsCollector.sol"; interface ITAPCollector is IPaymentsCollector { @@ -16,4 +17,16 @@ interface ITAPCollector is IPaymentsCollector { ReceiptAggregateVoucher rav; bytes signature; // 65 bytes: r (32 Bytes) || s (32 Bytes) || v (1 Byte) } + + event TAPCollectorCollected( + IGraphPayments.PaymentTypes indexed paymentType, + address indexed payer, + address receiver, + uint256 tokensReceiver, + address indexed dataService, + uint256 tokensDataService + ); + + error TAPCollectorCallerNotDataService(address caller, address dataService); + error TAPCollectorInconsistentRAVTokens(uint256 tokens, uint256 tokensCollected); } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 992ad7069..649107997 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -79,11 +79,7 @@ interface IHorizonStakingExtension { uint256 delegationRewards ); - /** - * @dev Emitted when `indexer` set `operator` access in the legacy contract, - * which now means only for the subgraph data service. - */ - event SetOperator(address indexed indexer, address indexed operator, bool allowed); + event CounterpartStakingAddressSet(address indexed counterpart); /** * @notice Set the address of the counterpart (L1 or L2) staking contract. diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 80613c018..e88015900 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -91,7 +91,7 @@ interface IHorizonStakingMain is IHorizonStakingBase { event AllowedLockedVerifierSet(address verifier, bool allowed); - event TokensAddedToDelegationPool(address indexed serviceProvider, address indexed verifier, uint256 tokens); + event TokensToDelegationPoolAdded(address indexed serviceProvider, address indexed verifier, uint256 tokens); event ProvisionParametersStaged( address indexed serviceProvider, @@ -107,6 +107,9 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint64 thawingPeriod ); + event ThawingPeriodCleared(); + event MaxThawingPeriodSet(uint64 maxThawingPeriod); + /** * @dev Emitted when an operator is allowed or denied by a service provider for a particular data service */ @@ -120,13 +123,10 @@ interface IHorizonStakingMain is IHorizonStakingBase { ); error HorizonStakingInvalidVerifier(address verifier); - error HorizonStakingVerifierAlreadyAllowed(address verifier); - error HorizonStakingVerifierNotAllowed(address verifier); error HorizonStakingInvalidZeroTokens(); error HorizonStakingInvalidProvision(address serviceProvider, address verifier); error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); error HorizonStakingInsufficientCapacity(); - error HorizonStakingInsufficientShares(); error HorizonStakingInsufficientCapacityForLegacyAllocations(); error HorizonStakingTooManyThawRequests(); error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index bab59365d..3831514d3 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -25,13 +25,6 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora uint256 tokensProtocol ); - // -- Errors -- - - error GraphPaymentsNotThawing(); - error GraphPaymentsStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); - error GraphPaymentsCollectorNotAuthorized(address sender, address dataService); - error GraphPaymentsInsufficientTokens(uint256 available, uint256 required); - // -- Events -- // -- Modifier -- diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index fd30bd758..4ce4a029b 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -31,37 +31,6 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn uint256 public immutable WITHDRAW_ESCROW_THAWING_PERIOD; - // -- Events -- - - event AuthorizedCollector(address indexed payer, address indexed dataService); - event ThawCollector(address indexed payer, address indexed dataService); - event CancelThawCollector(address indexed payer, address indexed dataService); - event RevokeCollector(address indexed payer, address indexed dataService); - event Deposit(address indexed payer, address indexed receiver, uint256 tokens); - event CancelThaw(address indexed payer, address indexed receiver); - event Thaw( - address indexed payer, - address indexed receiver, - uint256 tokens, - uint256 totalTokensThawing, - uint256 thawEndTimestamp - ); - event Withdraw(address indexed payer, address indexed receiver, uint256 tokens); - event EscrowCollected(address indexed payer, address indexed receiver, uint256 tokens); - - // -- Errors -- - - error GraphEscrowNotGraphPayments(); - error GraphEscrowInputsLengthMismatch(); - error GraphEscrowInsufficientTokensThawing(); - error GraphEscrowInsufficientBalance(uint256 available, uint256 required); - error GraphEscrowNotThawing(); - error GraphEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); - error GraphEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); - error GraphEscrowCollectorNotAuthorized(address sender, address dataService); - error GraphEscrowInsufficientAllowance(uint256 available, uint256 required); - error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); - // -- Constructor -- constructor( @@ -70,11 +39,11 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { uint256 withdrawEscrowThawingPeriod ) GraphDirectory(controller) { if (revokeCollectorThawingPeriod > MAX_THAWING_PERIOD) { - revert GraphEscrowThawingPeriodTooLong(revokeCollectorThawingPeriod, MAX_THAWING_PERIOD); + revert PaymentsEscrowThawingPeriodTooLong(revokeCollectorThawingPeriod, MAX_THAWING_PERIOD); } if (withdrawEscrowThawingPeriod > MAX_THAWING_PERIOD) { - revert GraphEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD); + revert PaymentsEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD); } REVOKE_COLLECTOR_THAWING_PERIOD = revokeCollectorThawingPeriod; @@ -85,7 +54,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { function approveCollector(address dataService, uint256 tokens) external { Collector storage collector = authorizedCollectors[msg.sender][dataService]; if (collector.allowance > tokens) { - revert GraphEscrowInsufficientAllowance(collector.allowance, tokens); + revert PaymentsEscrowInsufficientAllowance(collector.allowance, tokens); } collector.authorized = true; @@ -104,7 +73,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // cancel thawing a data service's collector authorization function cancelThawCollector(address dataService) external { if (authorizedCollectors[msg.sender][dataService].thawEndTimestamp == 0) { - revert GraphEscrowNotThawing(); + revert PaymentsEscrowNotThawing(); } authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; @@ -116,11 +85,11 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { Collector storage collector = authorizedCollectors[msg.sender][dataService]; if (collector.thawEndTimestamp == 0) { - revert GraphEscrowNotThawing(); + revert PaymentsEscrowNotThawing(); } if (collector.thawEndTimestamp > block.timestamp) { - revert GraphEscrowStillThawing(block.timestamp, collector.thawEndTimestamp); + revert PaymentsEscrowStillThawing(block.timestamp, collector.thawEndTimestamp); } delete authorizedCollectors[msg.sender][dataService]; @@ -142,7 +111,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // otherwise if amount thawing is greater than zero and requested amount is zero this // is a cancel thaw request. if (account.tokensThawing == 0) { - revert GraphEscrowInsufficientTokensThawing(); + revert PaymentsEscrowInsufficientTokensThawing(); } account.tokensThawing = 0; account.thawEndTimestamp = 0; @@ -152,7 +121,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // Check if the escrow balance is sufficient if (account.balance < tokens) { - revert GraphEscrowInsufficientBalance(account.balance, tokens); + revert PaymentsEscrowInsufficientBalance(account.balance, tokens); } // Set amount to thaw @@ -167,11 +136,11 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { function withdraw(address receiver) external { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; if (account.thawEndTimestamp == 0) { - revert GraphEscrowNotThawing(); + revert PaymentsEscrowNotThawing(); } if (account.thawEndTimestamp > block.timestamp) { - revert GraphEscrowStillThawing({ + revert PaymentsEscrowStillThawing({ currentTimestamp: block.timestamp, thawEndTimestamp: account.thawEndTimestamp }); @@ -200,21 +169,21 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { Collector storage collector = authorizedCollectors[payer][msg.sender]; if (!collector.authorized) { - revert GraphEscrowCollectorNotAuthorized(payer, msg.sender); + revert PaymentsEscrowCollectorNotAuthorized(payer, msg.sender); } if (collector.allowance < tokens) { - revert GraphEscrowInsufficientAllowance(collector.allowance, tokens); + revert PaymentsEscrowInsufficientAllowance(collector.allowance, tokens); } // Reduce amount from approved collector collector.allowance -= tokens; - // Collect tokens from GraphEscrow up to amount available + // Collect tokens from PaymentsEscrow up to amount available EscrowAccount storage account = escrowAccounts[payer][receiver]; uint256 availableTokens = account.balance - account.tokensThawing; if (availableTokens < tokens) { - revert GraphEscrowInsufficientBalance(availableTokens, tokens); + revert PaymentsEscrowInsufficientBalance(availableTokens, tokens); } account.balance -= tokens; diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index 94f601ad5..067bfce7c 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -25,19 +25,6 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { mapping(address dataService => mapping(address receiver => mapping(address payer => uint256 tokens))) public tokensCollected; - event TAPCollectorCollected( - IGraphPayments.PaymentTypes indexed paymentType, - address indexed payer, - address receiver, - uint256 tokensReceiver, - address indexed dataService, - uint256 tokensDataService - ); - - error TAPCollectorCallerNotDataService(address caller, address dataService); - error TAPVerifierInvalidSignerProof(); - error TAPCollectorInconsistentRAVTokens(uint256 tokens, uint256 tokensCollected); - /** * @dev Constructs a new instance of the TAPVerifier contract. */ diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 616efca8a..ced8e0fd2 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -332,7 +332,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); pool.tokens = pool.tokens + tokens; - emit TokensAddedToDelegationPool(serviceProvider, verifier, tokens); + emit TokensToDelegationPoolAdded(serviceProvider, verifier, tokens); } // undelegate tokens from a service provider @@ -536,12 +536,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // To be called at the end of the transition period, to set the deprecated thawing period to 0 function clearThawingPeriod() external onlyGovernor { __DEPRECATED_thawingPeriod = 0; - emit ParameterUpdated("thawingPeriod"); + emit ThawingPeriodCleared(); } function setMaxThawingPeriod(uint64 maxThawingPeriod) external override onlyGovernor { maxThawingPeriod = _maxThawingPeriod; - emit ParameterUpdated("maxThawingPeriod"); + emit MaxThawingPeriodSet(_maxThawingPeriod); } /* diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index ce53e2860..97d9af0b0 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -90,7 +90,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki */ function setCounterpartStakingAddress(address counterpart) external override onlyGovernor { _counterpartStakingAddress = counterpart; - emit ParameterUpdated("counterpartStakingAddress"); + emit CounterpartStakingAddressSet(counterpart); } /** diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index 459d807b5..c56e6ad2d 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -23,11 +23,6 @@ abstract contract Managed is GraphDirectory { /// @dev Gap for future storage variables uint256[10] private __gap; - // -- Events -- - - /// Emitted when a contract parameter has been updated - event ParameterUpdated(string param); - /** * @dev Revert if the controller is paused or partially paused */ diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 9eda3f42d..7570ddf54 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -44,104 +44,6 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM using TokenUtils for IGraphToken; using PPMMath for uint256; - // -- Events -- - event ArbitratorSet(address arbitrator); - event DisputePeriodSet(uint64 disputePeriod); - event MinimumDepositSet(uint256 minimumDeposit); - event MaxSlashingCutSet(uint32 maxSlashingCut); - event FishermanRewardCutSet(uint32 fishermanRewardCut); - event SubgraphServiceSet(address indexed subgraphService); - - /** - * @dev 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. - */ - event QueryDisputeCreated( - bytes32 indexed disputeId, - address indexed indexer, - address indexed fisherman, - uint256 tokens, - bytes32 subgraphDeploymentId, - bytes attestation - ); - - /** - * @dev Emitted when an indexing dispute is created for `allocationId` and `indexer` - * by `fisherman`. - * The event emits the amount of `tokens` deposited by the fisherman. - */ - event IndexingDisputeCreated( - bytes32 indexed disputeId, - address indexed indexer, - address indexed fisherman, - uint256 tokens, - address allocationId - ); - - /** - * @dev 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. - */ - event DisputeAccepted( - bytes32 indexed disputeId, - address indexed indexer, - address indexed fisherman, - uint256 tokens - ); - - /** - * @dev Emitted when arbitrator rejects a `disputeId` for `indexer` created by `fisherman`. - * The event emits the amount `tokens` burned from the fisherman deposit. - */ - event DisputeRejected( - bytes32 indexed disputeId, - address indexed indexer, - address indexed fisherman, - uint256 tokens - ); - - /** - * @dev 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. - */ - event DisputeDrawn(bytes32 indexed disputeId, address indexed indexer, address indexed fisherman, uint256 tokens); - - /** - * @dev 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. - */ - event DisputeLinked(bytes32 indexed disputeId1, bytes32 indexed disputeId2); - - // -- Errors -- - - error DisputeManagerNotArbitrator(); - error DisputeManagerNotFisherman(); - error DisputeManagerInvalidZeroAddress(); - error DisputeManagerDisputePeriodZero(); - error DisputeManagerZeroTokens(); - error DisputeManagerInvalidDispute(bytes32 disputeId); - error DisputeManagerInvalidMinimumDeposit(uint256 minimumDeposit); - error DisputeManagerInvalidFishermanReward(uint32 cut); - error DisputeManagerInvalidMaxSlashingCut(uint32 maxSlashingCut); - error DisputeManagerInvalidTokensSlash(uint256 tokensSlash); - error DisputeManagerInvalidDisputeStatus(IDisputeManager.DisputeStatus status); - error DisputeManagerInsufficientDeposit(uint256 deposit, uint256 minimumDeposit); - error DisputeManagerDisputeAlreadyCreated(bytes32 disputeId); - error DisputeManagerDisputePeriodNotFinished(); - error DisputeManagerMustAcceptRelatedDispute(bytes32 disputeId, bytes32 relatedDisputeId); - error DisputeManagerIndexerNotFound(address allocationId); - error DisputeManagerNonMatchingSubgraphDeployment(bytes32 subgraphDeploymentId1, bytes32 subgraphDeploymentId2); - error DisputeManagerNonConflictingAttestations( - bytes32 requestCID1, - bytes32 responseCID1, - bytes32 subgraphDeploymentId1, - bytes32 requestCID2, - bytes32 responseCID2, - bytes32 subgraphDeploymentId2 - ); - // -- Modifiers -- /** diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index b252346a5..de0168619 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.24; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; -import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; +import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { DataServicePausable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServicePausable.sol"; @@ -35,19 +35,6 @@ contract SubgraphService is using PPMMath for uint256; using Allocation for mapping(address => Allocation.State); - event QueryFeesCollected( - address serviceProvider, - uint256 tokensCollected, - uint256 tokensCurators, - uint256 tokensSubgraphService - ); - - error SubgraphServiceEmptyUrl(); - error SubgraphServiceInvalidPaymentType(IGraphPayments.PaymentTypes feeType); - error SubgraphServiceIndexerAlreadyRegistered(); - error SubgraphServiceIndexerNotRegistered(address indexer); - error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); - modifier onlyRegisteredIndexer(address indexer) { if (indexers[indexer].registeredAt == 0) { revert SubgraphServiceIndexerNotRegistered(indexer); diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 8c3df586d..8e6f9441b 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -33,6 +33,104 @@ interface IDisputeManager { uint256 createdAt; } + // -- Events -- + event ArbitratorSet(address arbitrator); + event DisputePeriodSet(uint64 disputePeriod); + event MinimumDepositSet(uint256 minimumDeposit); + event MaxSlashingCutSet(uint32 maxSlashingCut); + event FishermanRewardCutSet(uint32 fishermanRewardCut); + event SubgraphServiceSet(address indexed subgraphService); + + /** + * @dev 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. + */ + event QueryDisputeCreated( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens, + bytes32 subgraphDeploymentId, + bytes attestation + ); + + /** + * @dev Emitted when an indexing dispute is created for `allocationId` and `indexer` + * by `fisherman`. + * The event emits the amount of `tokens` deposited by the fisherman. + */ + event IndexingDisputeCreated( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens, + address allocationId + ); + + /** + * @dev 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. + */ + event DisputeAccepted( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens + ); + + /** + * @dev Emitted when arbitrator rejects a `disputeId` for `indexer` created by `fisherman`. + * The event emits the amount `tokens` burned from the fisherman deposit. + */ + event DisputeRejected( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens + ); + + /** + * @dev 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. + */ + event DisputeDrawn(bytes32 indexed disputeId, address indexed indexer, address indexed fisherman, uint256 tokens); + + /** + * @dev 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. + */ + event DisputeLinked(bytes32 indexed disputeId1, bytes32 indexed disputeId2); + + // -- Errors -- + + error DisputeManagerNotArbitrator(); + error DisputeManagerNotFisherman(); + error DisputeManagerInvalidZeroAddress(); + error DisputeManagerDisputePeriodZero(); + error DisputeManagerZeroTokens(); + error DisputeManagerInvalidDispute(bytes32 disputeId); + error DisputeManagerInvalidMinimumDeposit(uint256 minimumDeposit); + error DisputeManagerInvalidFishermanReward(uint32 cut); + error DisputeManagerInvalidMaxSlashingCut(uint32 maxSlashingCut); + error DisputeManagerInvalidTokensSlash(uint256 tokensSlash); + error DisputeManagerInvalidDisputeStatus(IDisputeManager.DisputeStatus status); + error DisputeManagerInsufficientDeposit(uint256 deposit, uint256 minimumDeposit); + error DisputeManagerDisputeAlreadyCreated(bytes32 disputeId); + error DisputeManagerDisputePeriodNotFinished(); + error DisputeManagerMustAcceptRelatedDispute(bytes32 disputeId, bytes32 relatedDisputeId); + error DisputeManagerIndexerNotFound(address allocationId); + error DisputeManagerNonMatchingSubgraphDeployment(bytes32 subgraphDeploymentId1, bytes32 subgraphDeploymentId2); + error DisputeManagerNonConflictingAttestations( + bytes32 requestCID1, + bytes32 responseCID1, + bytes32 subgraphDeploymentId1, + bytes32 requestCID2, + bytes32 responseCID2, + bytes32 subgraphDeploymentId2 + ); + // -- Attestation -- // -- Configuration -- diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 0cf65f37f..f7730036c 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.24; import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataServiceFees.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; @@ -18,6 +19,19 @@ interface ISubgraphService is IDataServiceFees { uint128 curationCut; } + event QueryFeesCollected( + address serviceProvider, + uint256 tokensCollected, + uint256 tokensCurators, + uint256 tokensSubgraphService + ); + + error SubgraphServiceEmptyUrl(); + error SubgraphServiceInvalidPaymentType(IGraphPayments.PaymentTypes feeType); + error SubgraphServiceIndexerAlreadyRegistered(); + error SubgraphServiceIndexerNotRegistered(address indexer); + error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); + function resizeAllocation(address indexer, address allocationId, uint256 tokens) external; function migrateLegacyAllocation(address indexer, address allocationId, bytes32 subgraphDeploymentID) external; From 5542532dfc44560dfef1b14daafb0554fede44b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 14:43:12 -0300 Subject: [PATCH 067/277] chore: update provision event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../interfaces/internal/IHorizonStakingMain.sol | 2 +- .../horizon/contracts/staking/HorizonStaking.sol | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index e88015900..9036be8c4 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -122,7 +122,6 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 feeCut ); - error HorizonStakingInvalidVerifier(address verifier); error HorizonStakingInvalidZeroTokens(); error HorizonStakingInvalidProvision(address serviceProvider, address verifier); error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); @@ -131,6 +130,7 @@ interface IHorizonStakingMain is IHorizonStakingBase { error HorizonStakingTooManyThawRequests(); error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); error HorizonStakingSlippageProtection(uint256 minExpectedShares, uint256 actualShares); + error HorizonStakingVerifierNotAllowed(address verifier); // deposit stake function stake(uint256 tokens) external; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index ced8e0fd2..728372269 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -173,10 +173,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 maxVerifierCut, uint64 thawingPeriod ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { - if (_getIdleStake(serviceProvider) < tokens) { - revert HorizonStakingInsufficientCapacity(); - } - _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } @@ -504,18 +500,15 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 maxVerifierCut, uint64 thawingPeriod ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { - if (_getIdleStake(serviceProvider) < tokens) { - revert HorizonStakingInsufficientCapacity(); - } if (!_allowedLockedVerifiers[verifier]) { - revert HorizonStakingInvalidVerifier(verifier); + revert HorizonStakingVerifierNotAllowed(verifier); } _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } // for vesting contracts function setOperatorLocked(address operator, address verifier, bool allowed) external override { - require(_allowedLockedVerifiers[verifier], "VERIFIER_NOT_ALLOWED"); + if (!_allowedLockedVerifiers[verifier]) revert HorizonStakingVerifierNotAllowed(verifier); _setOperator(operator, verifier, allowed); } @@ -648,6 +641,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 _maxVerifierCut, uint64 _thawingPeriod ) private { + if (_getIdleStake(_serviceProvider) < _tokens) { + revert HorizonStakingInsufficientCapacity(); + } require(_tokens >= MIN_PROVISION_SIZE, "!tokens"); require(_maxVerifierCut <= MAX_MAX_VERIFIER_CUT, "maxVerifierCut too high"); require(_thawingPeriod <= _maxThawingPeriod, "thawingPeriod too high"); From 6255c48dcb9e451cae1eda253d8399a2d1ed9a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 14:46:01 -0300 Subject: [PATCH 068/277] feat: updated solidity to 0.8.26 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/contracts/contracts/arbitrum/ITokenGateway.sol | 2 +- packages/contracts/contracts/curation/ICuration.sol | 2 +- packages/contracts/contracts/epochs/IEpochManager.sol | 2 +- packages/contracts/contracts/gateway/ICallhookReceiver.sol | 2 +- packages/contracts/contracts/governance/Controller.sol | 2 +- packages/contracts/contracts/governance/Governed.sol | 2 +- packages/contracts/contracts/governance/IController.sol | 2 +- packages/contracts/contracts/governance/IManaged.sol | 2 +- packages/contracts/contracts/governance/Pausable.sol | 2 +- packages/contracts/contracts/l2/staking/IL2StakingBase.sol | 2 +- packages/contracts/contracts/l2/staking/IL2StakingTypes.sol | 2 +- packages/contracts/contracts/rewards/IRewardsIssuer.sol | 2 +- packages/contracts/contracts/rewards/IRewardsManager.sol | 2 +- packages/contracts/contracts/token/IGraphToken.sol | 2 +- packages/contracts/contracts/upgrades/GraphProxy.sol | 2 +- packages/contracts/contracts/upgrades/GraphProxyAdmin.sol | 2 +- packages/contracts/contracts/upgrades/GraphProxyStorage.sol | 2 +- packages/contracts/contracts/upgrades/GraphUpgradeable.sol | 2 +- packages/contracts/contracts/upgrades/IGraphProxy.sol | 2 +- packages/contracts/contracts/utils/TokenUtils.sol | 2 +- packages/horizon/contracts/data-service/DataService.sol | 2 +- packages/horizon/contracts/data-service/DataServiceStorage.sol | 2 +- packages/horizon/contracts/data-service/GraphDirectory.sol | 2 +- .../contracts/data-service/extensions/DataServiceFees.sol | 2 +- .../data-service/extensions/DataServiceFeesStorage.sol | 2 +- .../contracts/data-service/extensions/DataServicePausable.sol | 2 +- .../contracts/data-service/extensions/DataServiceRescuable.sol | 2 +- .../horizon/contracts/data-service/interfaces/IDataService.sol | 2 +- .../contracts/data-service/interfaces/IDataServiceFees.sol | 2 +- .../contracts/data-service/interfaces/IDataServicePausable.sol | 2 +- .../contracts/data-service/interfaces/IDataServiceRescuable.sol | 2 +- .../contracts/data-service/libraries/ProvisionGetter.sol | 2 +- .../contracts/data-service/libraries/ProvisionTracker.sol | 2 +- .../contracts/data-service/utilities/ProvisionManager.sol | 2 +- .../data-service/utilities/ProvisionManagerStorage.sol | 2 +- packages/horizon/contracts/interfaces/IBridgeEscrow.sol | 2 +- packages/horizon/contracts/interfaces/IGraphPayments.sol | 2 +- packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol | 2 +- packages/horizon/contracts/interfaces/IHorizonStaking.sol | 2 +- packages/horizon/contracts/interfaces/IPaymentsCollector.sol | 2 +- packages/horizon/contracts/interfaces/IPaymentsEscrow.sol | 2 +- packages/horizon/contracts/interfaces/ITAPCollector.sol | 2 +- .../contracts/interfaces/internal/IHorizonStakingBase.sol | 2 +- .../contracts/interfaces/internal/IHorizonStakingExtension.sol | 2 +- .../contracts/interfaces/internal/IHorizonStakingMain.sol | 2 +- .../contracts/interfaces/internal/IHorizonStakingTypes.sol | 2 +- packages/horizon/contracts/libraries/Denominations.sol | 2 +- packages/horizon/contracts/libraries/LibFixedMath.sol | 2 +- packages/horizon/contracts/libraries/MathUtils.sol | 2 +- packages/horizon/contracts/libraries/PPMMath.sol | 2 +- packages/horizon/contracts/libraries/UintRange.sol | 2 +- packages/horizon/contracts/mocks/ControllerMock.sol | 2 +- packages/horizon/contracts/mocks/MockGRTToken.sol | 2 +- packages/horizon/contracts/payments/GraphPayments.sol | 2 +- packages/horizon/contracts/payments/GraphPaymentsStorage.sol | 2 +- packages/horizon/contracts/payments/PaymentsEscrow.sol | 2 +- packages/horizon/contracts/payments/collectors/TAPCollector.sol | 2 +- packages/horizon/contracts/staking/HorizonStaking.sol | 2 +- packages/horizon/contracts/staking/HorizonStakingBase.sol | 2 +- packages/horizon/contracts/staking/HorizonStakingExtension.sol | 2 +- packages/horizon/contracts/staking/HorizonStakingStorage.sol | 2 +- .../horizon/contracts/staking/libraries/ExponentialRebates.sol | 2 +- packages/horizon/contracts/staking/utilities/Managed.sol | 2 +- packages/horizon/hardhat.config.ts | 2 +- packages/horizon/test/GraphBase.t.sol | 2 +- packages/horizon/test/deployments/Deployments.t.sol | 2 +- packages/horizon/test/escrow/GraphEscrow.t.sol | 2 +- packages/horizon/test/escrow/collect.t.sol | 2 +- packages/horizon/test/escrow/collector.t.sol | 2 +- packages/horizon/test/escrow/deposit.t.sol | 2 +- packages/horizon/test/escrow/thaw.t.sol | 2 +- packages/horizon/test/escrow/withdraw.t.sol | 2 +- packages/horizon/test/payments/GraphPayments.t.sol | 2 +- .../horizon/test/shared/horizon-staking/HorizonStaking.t.sol | 2 +- packages/horizon/test/utils/Constants.sol | 2 +- packages/horizon/test/utils/Users.sol | 2 +- packages/subgraph-service/contracts/DisputeManager.sol | 2 +- packages/subgraph-service/contracts/DisputeManagerStorage.sol | 2 +- packages/subgraph-service/contracts/SubgraphService.sol | 2 +- packages/subgraph-service/contracts/SubgraphServiceStorage.sol | 2 +- .../subgraph-service/contracts/interfaces/IDisputeManager.sol | 2 +- .../subgraph-service/contracts/interfaces/ISubgraphService.sol | 2 +- packages/subgraph-service/contracts/libraries/Allocation.sol | 2 +- packages/subgraph-service/contracts/libraries/Attestation.sol | 2 +- .../subgraph-service/contracts/libraries/LegacyAllocation.sol | 2 +- .../subgraph-service/contracts/utilities/AllocationManager.sol | 2 +- .../contracts/utilities/AllocationManagerStorage.sol | 2 +- .../subgraph-service/contracts/utilities/AttestationManager.sol | 2 +- .../contracts/utilities/AttestationManagerStorage.sol | 2 +- packages/subgraph-service/contracts/utilities/Directory.sol | 2 +- packages/subgraph-service/hardhat.config.ts | 2 +- packages/subgraph-service/test/DisputeManager.t.sol | 2 +- packages/subgraph-service/test/mocks/MockGRTToken.sol | 2 +- packages/subgraph-service/test/mocks/MockHorizonStaking.sol | 2 +- packages/subgraph-service/test/mocks/MockRewardsManager.sol | 2 +- 95 files changed, 95 insertions(+), 95 deletions(-) diff --git a/packages/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/contracts/contracts/arbitrum/ITokenGateway.sol index 6ac47d715..9fb440fd2 100644 --- a/packages/contracts/contracts/arbitrum/ITokenGateway.sol +++ b/packages/contracts/contracts/arbitrum/ITokenGateway.sol @@ -23,7 +23,7 @@ * */ -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface ITokenGateway { /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated diff --git a/packages/contracts/contracts/curation/ICuration.sol b/packages/contracts/contracts/curation/ICuration.sol index b57efaf2a..635b45a0c 100644 --- a/packages/contracts/contracts/curation/ICuration.sol +++ b/packages/contracts/contracts/curation/ICuration.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; /** * @title Curation Interface diff --git a/packages/contracts/contracts/epochs/IEpochManager.sol b/packages/contracts/contracts/epochs/IEpochManager.sol index 5f02e3579..23c55f15b 100644 --- a/packages/contracts/contracts/epochs/IEpochManager.sol +++ b/packages/contracts/contracts/epochs/IEpochManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface IEpochManager { // -- Configuration -- diff --git a/packages/contracts/contracts/gateway/ICallhookReceiver.sol b/packages/contracts/contracts/gateway/ICallhookReceiver.sol index e869c7f4e..0fc27cf23 100644 --- a/packages/contracts/contracts/gateway/ICallhookReceiver.sol +++ b/packages/contracts/contracts/gateway/ICallhookReceiver.sol @@ -6,7 +6,7 @@ * be allowlisted by the governor, but also implement this interface that contains * the function that will actually be called by the L2GraphTokenGateway. */ -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface ICallhookReceiver { /** diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index 9c369b0b7..a24b96b4e 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import { IController } from "./IController.sol"; import { IManaged } from "./IManaged.sol"; diff --git a/packages/contracts/contracts/governance/Governed.sol b/packages/contracts/contracts/governance/Governed.sol index 0d1c1250b..c9cf940db 100644 --- a/packages/contracts/contracts/governance/Governed.sol +++ b/packages/contracts/contracts/governance/Governed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; /** * @title Graph Governance contract diff --git a/packages/contracts/contracts/governance/IController.sol b/packages/contracts/contracts/governance/IController.sol index 634c881d3..093a0303a 100644 --- a/packages/contracts/contracts/governance/IController.sol +++ b/packages/contracts/contracts/governance/IController.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface IController { function getGovernor() external view returns (address); diff --git a/packages/contracts/contracts/governance/IManaged.sol b/packages/contracts/contracts/governance/IManaged.sol index 5ef387b5d..59f44dd9a 100644 --- a/packages/contracts/contracts/governance/IManaged.sol +++ b/packages/contracts/contracts/governance/IManaged.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import { IController } from "./IController.sol"; diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 9ebf36a1c..8564b9c09 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; abstract contract Pausable { /** diff --git a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol index 9ae4b850b..8c0b145de 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; diff --git a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol index 2bc452a4a..086f88e77 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface IL2StakingTypes { /// @dev Message codes for the L1 -> L2 bridge callhook diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol index 67588aee3..21dcc8768 100644 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface IRewardsIssuer { /** diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index 5c4de5461..1602fe91e 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface IRewardsManager { /** diff --git a/packages/contracts/contracts/token/IGraphToken.sol b/packages/contracts/contracts/token/IGraphToken.sol index 1342625df..f6f1c00f6 100644 --- a/packages/contracts/contracts/token/IGraphToken.sol +++ b/packages/contracts/contracts/token/IGraphToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxy.sol b/packages/contracts/contracts/upgrades/GraphProxy.sol index a95428f68..cb52ab1dc 100644 --- a/packages/contracts/contracts/upgrades/GraphProxy.sol +++ b/packages/contracts/contracts/upgrades/GraphProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import { GraphProxyStorage } from "./GraphProxyStorage.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol index 0d3b075a5..55bbd2176 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import { Governed } from "../governance/Governed.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol index 9117ff54d..cd076c118 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; /** * @title Graph Proxy Storage diff --git a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol index 2627e7578..ffc47aa40 100644 --- a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol +++ b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import { IGraphProxy } from "./IGraphProxy.sol"; diff --git a/packages/contracts/contracts/upgrades/IGraphProxy.sol b/packages/contracts/contracts/upgrades/IGraphProxy.sol index 59d4a323d..e81722e3f 100644 --- a/packages/contracts/contracts/upgrades/IGraphProxy.sol +++ b/packages/contracts/contracts/upgrades/IGraphProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; interface IGraphProxy { function admin() external returns (address); diff --git a/packages/contracts/contracts/utils/TokenUtils.sol b/packages/contracts/contracts/utils/TokenUtils.sol index f33bc5c85..a34059a1d 100644 --- a/packages/contracts/contracts/utils/TokenUtils.sol +++ b/packages/contracts/contracts/utils/TokenUtils.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.24; +pragma solidity ^0.7.6 || 0.8.26; import "../token/IGraphToken.sol"; diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index b2c39b6b0..681d13f73 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataService } from "./interfaces/IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/DataServiceStorage.sol b/packages/horizon/contracts/data-service/DataServiceStorage.sol index 92e73e690..03b060515 100644 --- a/packages/horizon/contracts/data-service/DataServiceStorage.sol +++ b/packages/horizon/contracts/data-service/DataServiceStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; abstract contract DataServiceV1Storage { /// @dev Gap to allow adding variables in future upgrades diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index 6171e06c8..63a6aec48 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 4770ebc41..150c5cd27 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 7069b9bb6..814d246a7 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index d1800ad38..e02f1776e 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataServicePausable } from "../interfaces/IDataServicePausable.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 8fff2947d..bd77533c6 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IDataServiceRescuable } from "../interfaces/IDataServiceRescuable.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index 3406c7029..6814ef23e 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index b5d5d88d5..bbbab0d8b 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol index 2c89ca860..673238b7f 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index 4762fd349..f1494413f 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol b/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol index f0ef2d382..a8e44b1c4 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index cc86b71e3..5fb9230cf 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index f13adecf8..4fba72985 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index 6e62d134c..7f4e507a5 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; abstract contract ProvisionManagerV1Storage { /// @notice The minimum amount of tokens required to register a provision in the data service diff --git a/packages/horizon/contracts/interfaces/IBridgeEscrow.sol b/packages/horizon/contracts/interfaces/IBridgeEscrow.sol index 19a13a0f2..4e0021423 100644 --- a/packages/horizon/contracts/interfaces/IBridgeEscrow.sol +++ b/packages/horizon/contracts/interfaces/IBridgeEscrow.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; /** * @title IBridgeEscrow diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 9002185c6..8c52b18be 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; interface IGraphPayments { // Payment types diff --git a/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol b/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol index 2abf4517d..6bc063057 100644 --- a/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol +++ b/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; /** * @title IGraphProxyAdmin diff --git a/packages/horizon/contracts/interfaces/IHorizonStaking.sol b/packages/horizon/contracts/interfaces/IHorizonStaking.sol index 13d9f19f6..647e66320 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStaking.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStaking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStakingTypes } from "./internal/IHorizonStakingTypes.sol"; import { IHorizonStakingMain } from "./internal/IHorizonStakingMain.sol"; diff --git a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol index 76525bd03..f076ef3e0 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "./IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index db5c56218..db8320aea 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "./IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 50db686c9..46209bb2d 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "./IGraphPayments.sol"; import { IPaymentsCollector } from "./IPaymentsCollector.sol"; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index 2483ebda4..0d367547f 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; import { IGraphPayments } from "../IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 649107997..d09bbc3c3 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; /** * @title Base interface for the Staking contract. diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 9036be8c4..d0a962071 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index f95fff4c4..d320dd643 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; // TODO: create custom var-name-mixedcase /* solhint-disable var-name-mixedcase */ diff --git a/packages/horizon/contracts/libraries/Denominations.sol b/packages/horizon/contracts/libraries/Denominations.sol index 201051447..5652f50a0 100644 --- a/packages/horizon/contracts/libraries/Denominations.sol +++ b/packages/horizon/contracts/libraries/Denominations.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; /** * @title Denominations diff --git a/packages/horizon/contracts/libraries/LibFixedMath.sol b/packages/horizon/contracts/libraries/LibFixedMath.sol index 487de84a8..fd29b5e53 100644 --- a/packages/horizon/contracts/libraries/LibFixedMath.sol +++ b/packages/horizon/contracts/libraries/LibFixedMath.sol @@ -18,7 +18,7 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.8.24; +pragma solidity 0.8.26; // solhint-disable indent /// @dev Signed, fixed-point, 127-bit precision math library. diff --git a/packages/horizon/contracts/libraries/MathUtils.sol b/packages/horizon/contracts/libraries/MathUtils.sol index 3df620b12..a5ad3f41a 100644 --- a/packages/horizon/contracts/libraries/MathUtils.sol +++ b/packages/horizon/contracts/libraries/MathUtils.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; /** * @title MathUtils Library diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index 3eb3a5b69..2bd5a51f9 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; library PPMMath { /// @notice Maximum value (100%) in parts per million (PPM). diff --git a/packages/horizon/contracts/libraries/UintRange.sol b/packages/horizon/contracts/libraries/UintRange.sol index d8265e35f..2e722e057 100644 --- a/packages/horizon/contracts/libraries/UintRange.sol +++ b/packages/horizon/contracts/libraries/UintRange.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; library UintRange { using UintRange for uint256; diff --git a/packages/horizon/contracts/mocks/ControllerMock.sol b/packages/horizon/contracts/mocks/ControllerMock.sol index a30993a89..82673dca6 100644 --- a/packages/horizon/contracts/mocks/ControllerMock.sol +++ b/packages/horizon/contracts/mocks/ControllerMock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; import { IManaged } from "@graphprotocol/contracts/contracts/governance/IManaged.sol"; diff --git a/packages/horizon/contracts/mocks/MockGRTToken.sol b/packages/horizon/contracts/mocks/MockGRTToken.sol index af50cbdfd..1a51f3b96 100644 --- a/packages/horizon/contracts/mocks/MockGRTToken.sol +++ b/packages/horizon/contracts/mocks/MockGRTToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 3831514d3..cb0123e32 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol index f05499249..409b42a80 100644 --- a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol +++ b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; contract GraphPaymentsStorageV1Storage { // The graph protocol payment cut diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 4ce4a029b..507c79393 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index 067bfce7c..6c50f8015 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; import { ITAPCollector } from "../../interfaces/ITAPCollector.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 728372269..16367b776 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingMain } from "../interfaces/internal/IHorizonStakingMain.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index e392a992b..951395b5b 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; import { IHorizonStakingBase } from "../interfaces/internal/IHorizonStakingBase.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 97d9af0b0..97fd49500 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index ff9a1e2bb..ffe82ab30 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IHorizonStakingExtension } from "../interfaces/internal/IHorizonStakingExtension.sol"; import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; diff --git a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol index 50579cafb..3cbc93aa0 100644 --- a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol +++ b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { LibFixedMath } from "../../libraries/LibFixedMath.sol"; diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index c56e6ad2d..de3a08214 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index 4e35d3b4e..fd31b26d4 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -7,7 +7,7 @@ import { HardhatUserConfig } from 'hardhat/config' const config: HardhatUserConfig = { solidity: { - version: '0.8.24', + version: '0.8.26', settings: { optimizer: { enabled: true, diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index b45797fdf..f657d8b3e 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/deployments/Deployments.t.sol b/packages/horizon/test/deployments/Deployments.t.sol index 2832bc69b..46abde654 100644 --- a/packages/horizon/test/deployments/Deployments.t.sol +++ b/packages/horizon/test/deployments/Deployments.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index c4041be16..a98eb3322 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 7317f9c0e..d7557353a 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index 1e3fd3fb8..f90eff6dc 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol index 05c6d557d..8e9839b9b 100644 --- a/packages/horizon/test/escrow/deposit.t.sol +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 72a1fc176..bf689486c 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index 6d70b64f7..15d1d94ed 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 655700c6a..e4fa18b97 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol index 464665d51..7fd428e40 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index 44ed15fdf..bcf3295d8 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; abstract contract Constants { uint256 internal constant MAX_PPM = 1000000; // 100% in parts per million diff --git a/packages/horizon/test/utils/Users.sol b/packages/horizon/test/utils/Users.sol index a834e18a9..e86bf8faf 100644 --- a/packages/horizon/test/utils/Users.sol +++ b/packages/horizon/test/utils/Users.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; struct Users { address governor; diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 7570ddf54..536fe187d 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol index c90ef885d..bf2b368d6 100644 --- a/packages/subgraph-service/contracts/DisputeManagerStorage.sol +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index de0168619..302e350bb 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 3904b7ba4..9d2ae9966 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 8e6f9441b..f6c9a1c56 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { Attestation } from "../libraries/Attestation.sol"; diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index f7730036c..3bf6ed711 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index 5d7dd4f82..bcbc666e6 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; library Allocation { using Allocation for State; diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index de85d9ca0..5d5771721 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; library Attestation { // Receipt content sent from the service provider in response to request diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol index 18b5bdb1e..840973cbf 100644 --- a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; library LegacyAllocation { using LegacyAllocation for State; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 4423473ea..69031bf44 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol index 525c83b54..700c0243c 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index 54b538c89..b68a6804d 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { AttestationManagerV1Storage } from "./AttestationManagerStorage.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol index 2841334ff..cfb925f5b 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; abstract contract AttestationManagerV1Storage { bytes32 internal _domainSeparator; diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index ca7a45a73..67afaadc5 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.24; +pragma solidity 0.8.26; import { IDisputeManager } from "../interfaces/IDisputeManager.sol"; import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts index f4a7067b7..4d951d967 100644 --- a/packages/subgraph-service/hardhat.config.ts +++ b/packages/subgraph-service/hardhat.config.ts @@ -10,7 +10,7 @@ const config: HardhatUserConfig = { solidity: { compilers: [ { - version: '0.8.24', + version: '0.8.26', settings: { optimizer: { enabled: true, diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol index 64838c6bb..b13fc8109 100644 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/mocks/MockGRTToken.sol b/packages/subgraph-service/test/mocks/MockGRTToken.sol index cab52fb35..d581f8299 100644 --- a/packages/subgraph-service/test/mocks/MockGRTToken.sol +++ b/packages/subgraph-service/test/mocks/MockGRTToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index 9efebeb60..c8ee45799 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index c98b60ca7..3e43e8109 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; From 9118567cdc9f873a27418405542ad9ecd50e1322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 15:41:48 -0300 Subject: [PATCH 069/277] chore: use IR to compile solidity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/foundry.toml | 1 + packages/horizon/hardhat.config.ts | 1 + packages/subgraph-service/foundry.toml | 5 ++++- packages/subgraph-service/hardhat.config.ts | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/horizon/foundry.toml b/packages/horizon/foundry.toml index 9f5c3a92a..c9e7f0534 100644 --- a/packages/horizon/foundry.toml +++ b/packages/horizon/foundry.toml @@ -7,3 +7,4 @@ cache_path = 'cache_forge' fs_permissions = [{ access = "read", path = "./"}] optimizer = true optimizer-runs = 200 +via_ir = true \ No newline at end of file diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index fd31b26d4..2d951261d 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -9,6 +9,7 @@ const config: HardhatUserConfig = { solidity: { version: '0.8.26', settings: { + viaIR: true, optimizer: { enabled: true, runs: 200, diff --git a/packages/subgraph-service/foundry.toml b/packages/subgraph-service/foundry.toml index 55f7ffd31..4c96e433b 100644 --- a/packages/subgraph-service/foundry.toml +++ b/packages/subgraph-service/foundry.toml @@ -3,4 +3,7 @@ src = 'contracts' out = 'build' libs = ['node_modules', 'lib'] test = 'test' -cache_path = 'cache_forge' \ No newline at end of file +cache_path = 'cache_forge' +optimizer = true +optimizer-runs = 200 +via_ir = true \ No newline at end of file diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts index 4d951d967..1db083d76 100644 --- a/packages/subgraph-service/hardhat.config.ts +++ b/packages/subgraph-service/hardhat.config.ts @@ -12,6 +12,7 @@ const config: HardhatUserConfig = { { version: '0.8.26', settings: { + viaIR: true, optimizer: { enabled: true, runs: 200, From 106f388b20e56f98f6394ddd4c7dad694ecb6603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 17:14:53 -0300 Subject: [PATCH 070/277] feat: use require with custom errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/GraphDirectory.sol | 10 +- .../extensions/DataServiceFees.sol | 4 +- .../extensions/DataServicePausable.sol | 4 +- .../extensions/DataServiceRescuable.sol | 6 +- .../libraries/ProvisionGetter.sol | 21 --- .../libraries/ProvisionTracker.sol | 9 +- .../utilities/ProvisionManager.sol | 18 +-- .../contracts/interfaces/IPaymentsEscrow.sol | 4 +- .../internal/IHorizonStakingMain.sol | 14 +- .../horizon/contracts/libraries/PPMMath.sol | 8 +- .../contracts/payments/GraphPayments.sol | 4 +- .../contracts/payments/PaymentsEscrow.sol | 79 ++++------ .../payments/collectors/TAPCollector.sol | 15 +- .../contracts/staking/HorizonStaking.sol | 147 +++++++++--------- .../contracts/staking/utilities/Managed.sol | 15 +- .../contracts/DisputeManager.sol | 115 +++++--------- .../contracts/SubgraphService.sol | 23 +-- .../contracts/interfaces/IDisputeManager.sol | 2 +- .../contracts/libraries/Allocation.sol | 13 +- .../contracts/libraries/Attestation.sol | 21 +-- .../contracts/libraries/LegacyAllocation.sol | 7 +- .../contracts/utilities/AllocationManager.sol | 22 +-- .../contracts/utilities/Directory.sol | 7 +- 23 files changed, 234 insertions(+), 334 deletions(-) delete mode 100644 packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index 63a6aec48..decb73e21 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -59,11 +59,9 @@ abstract contract GraphDirectory { error GraphDirectoryInvalidZeroAddress(bytes contractName); constructor(address controller) { - if (controller == address(0)) { - revert GraphDirectoryInvalidZeroAddress("Controller"); - } - GRAPH_CONTROLLER = IController(controller); + require(controller != address(0), GraphDirectoryInvalidZeroAddress("Controller")); + GRAPH_CONTROLLER = IController(controller); GRAPH_TOKEN = IGraphToken(_getContractFromController("GraphToken")); GRAPH_STAKING = IHorizonStaking(_getContractFromController("Staking")); GRAPH_PAYMENTS = IGraphPayments(_getContractFromController("GraphPayments")); @@ -136,9 +134,7 @@ abstract contract GraphDirectory { function _getContractFromController(bytes memory _contractName) private view returns (address) { address contractAddress = GRAPH_CONTROLLER.getContractProxy(keccak256(_contractName)); - if (contractAddress == address(0)) { - revert GraphDirectoryInvalidZeroAddress(_contractName); - } + require(contractAddress != address(0), GraphDirectoryInvalidZeroAddress(_contractName)); return contractAddress; } } diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 150c5cd27..cf8787674 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -72,9 +72,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat function _getStakeClaim(bytes32 _claimId) private view returns (StakeClaim memory) { StakeClaim memory claim = claims[_claimId]; - if (claim.createdAt == 0) { - revert DataServiceFeesClaimNotFound(_claimId); - } + require(claim.createdAt != 0, DataServiceFeesClaimNotFound(_claimId)); return claim; } diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index e02f1776e..43a09f3f2 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -10,9 +10,7 @@ abstract contract DataServicePausable is Pausable, DataService, IDataServicePaus mapping(address pauseGuardian => bool allowed) public pauseGuardians; modifier onlyPauseGuardian() { - if (!pauseGuardians[msg.sender]) { - revert DataServicePausableNotPauseGuardian(msg.sender); - } + require(pauseGuardians[msg.sender], DataServicePausableNotPauseGuardian(msg.sender)); _; } diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index bd77533c6..3fc23422d 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -19,9 +19,7 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { mapping(address rescuer => bool allowed) public rescuers; modifier onlyRescuer() { - if (!rescuers[msg.sender]) { - revert DataServiceRescuableNotRescuer(msg.sender); - } + require(rescuers[msg.sender], DataServiceRescuableNotRescuer(msg.sender)); _; } @@ -45,7 +43,7 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { * @param _tokens Amount of tokens to pull */ function _rescueTokens(address _to, address _token, uint256 _tokens) internal { - if (_tokens == 0) revert DataServiceRescuableCannotRescueZero(); + require(_tokens != 0, DataServiceRescuableCannotRescueZero()); if (Denominations.isNativeToken(_token)) payable(_to).transfer(_tokens); else SafeERC20.safeTransfer(IERC20(_token), _to, _tokens); diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol b/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol deleted file mode 100644 index a8e44b1c4..000000000 --- a/packages/horizon/contracts/data-service/libraries/ProvisionGetter.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; - -import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; - -library ProvisionGetter { - using ProvisionGetter for IHorizonStaking.Provision; - - error ProvisionGetterProvisionNotFound(address serviceProvider, address service); - - function get( - IHorizonStaking graphStaking, - address serviceProvider - ) internal view returns (IHorizonStaking.Provision memory) { - IHorizonStaking.Provision memory provision = graphStaking.getProvision(serviceProvider, address(this)); - if (provision.createdAt == 0) { - revert ProvisionGetterProvisionNotFound(serviceProvider, address(this)); - } - return provision; - } -} diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index 5fb9230cf..4358b33b2 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -17,18 +17,13 @@ library ProvisionTracker { uint256 tokensRequired = self[serviceProvider] + tokens; uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this), delegationRatio); - if (tokensRequired > tokensAvailable) { - revert ProvisionTrackerInsufficientTokens(tokensAvailable, tokensRequired); - } + require(tokensRequired <= tokensAvailable, ProvisionTrackerInsufficientTokens(tokensAvailable, tokensRequired)); self[serviceProvider] += tokens; } function release(mapping(address => uint256) storage self, address serviceProvider, uint256 tokens) internal { if (tokens == 0) return; - - if (tokens > self[serviceProvider]) { - revert ProvisionTrackerInsufficientTokens(self[serviceProvider], tokens); - } + require(self[serviceProvider] >= tokens, ProvisionTrackerInsufficientTokens(self[serviceProvider], tokens)); self[serviceProvider] -= tokens; } diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 4fba72985..c09a17ada 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -3,23 +3,23 @@ pragma solidity 0.8.26; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; -import { ProvisionGetter } from "../libraries/ProvisionGetter.sol"; import { UintRange } from "../../libraries/UintRange.sol"; import { GraphDirectory } from "../GraphDirectory.sol"; import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage { - using ProvisionGetter for IHorizonStaking; using UintRange for uint256; error ProvisionManagerInvalidValue(bytes message, uint256 value, uint256 min, uint256 max); error ProvisionManagerNotAuthorized(address caller, address serviceProvider, address service); + error ProvisionManagerProvisionNotFound(address serviceProvider, address service); modifier onlyProvisionAuthorized(address serviceProvider) { - if (!_graphStaking().isAuthorized(msg.sender, serviceProvider, address(this))) { - revert ProvisionManagerNotAuthorized(msg.sender, serviceProvider, address(this)); - } + require( + _graphStaking().isAuthorized(msg.sender, serviceProvider, address(this)), + ProvisionManagerNotAuthorized(msg.sender, serviceProvider, address(this)) + ); _; } @@ -123,12 +123,12 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage } function _getProvision(address _serviceProvider) internal view returns (IHorizonStaking.Provision memory) { - return _graphStaking().get(_serviceProvider); + IHorizonStaking.Provision memory provision = _graphStaking().getProvision(_serviceProvider, address(this)); + require(provision.createdAt != 0, ProvisionManagerProvisionNotFound(_serviceProvider, address(this))); + return provision; } function _checkValueInRange(uint256 _value, uint256 _min, uint256 _max, bytes memory _revertMessage) private pure { - if (!_value.isInRange(_min, _max)) { - revert ProvisionManagerInvalidValue(_revertMessage, _value, _min, _max); - } + require(_value.isInRange(_min, _max), ProvisionManagerInvalidValue(_revertMessage, _value, _min, _max)); } } diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index db8320aea..12b64cb87 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -43,9 +43,9 @@ interface IPaymentsEscrow { error PaymentsEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); error PaymentsEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); error PaymentsEscrowCollectorNotAuthorized(address sender, address dataService); - error PaymentsEscrowInsufficientAllowance(uint256 available, uint256 required); + error PaymentsEscrowInsufficientAllowance(uint256 current, uint256 required); + error PaymentsEscrowInconsistentAllowance(uint256 current, uint256 required); error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); - // Deposit funds into the escrow for a receiver function deposit(address receiver, uint256 tokens) external; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index d0a962071..27f63b3c8 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -124,13 +124,25 @@ interface IHorizonStakingMain is IHorizonStakingBase { error HorizonStakingInvalidZeroTokens(); error HorizonStakingInvalidProvision(address serviceProvider, address verifier); + error HorizonStakingInvalidTokens(uint256 tokens, uint256 minTokens); + error HorizonStakingInvalidMaxVerifierCut(uint32 maxVerifierCut, uint32 maxAllowedCut); + error HorizonStakingInvalidThawingPeriod(uint64 thawingPeriod, uint64 maxThawingPeriod); error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); error HorizonStakingInsufficientCapacity(); error HorizonStakingInsufficientCapacityForLegacyAllocations(); + error HorizonStakingInsufficientTokensAvailable(uint256 tokensAvailable, uint256 tokensRequired); error HorizonStakingTooManyThawRequests(); - error HorizonStakingInsufficientTokens(uint256 expected, uint256 available); + error HorizonStakingInsufficientTokens(uint256 available, uint256 tokensRequired); error HorizonStakingSlippageProtection(uint256 minExpectedShares, uint256 actualShares); error HorizonStakingVerifierNotAllowed(address verifier); + error HorizonStakingNothingThawing(); + error HorizonStakingVerifierTokensTooHigh(uint256 tokensVerifier, uint256 maxVerifierTokens); + error HorizonStakingNotEnoughDelegation(uint256 tokensAvailable, uint256 tokensRequired); + error HorizonStakingStillThawing(uint256 until); + error HorizonStakingInvalidZeroShares(); + error HorizonStakingInvalidSharesAmount(uint256 sharesAvailable, uint256 sharesRequired); + error HorizonStakingCallerIsServiceProvider(); + error HorizonStakingCannotFulfillThawRequest(); // deposit stake function stake(uint256 tokens) external; diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index 2bd5a51f9..f18e089ab 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -10,9 +10,7 @@ library PPMMath { // one of a or b must be in PPM function mulPPM(uint256 a, uint256 b) internal pure returns (uint256) { - if (!isValidPPM(a) && !isValidPPM(b)) { - revert PPMMathInvalidMulPPM(a, b); - } + require(isValidPPM(a) || isValidPPM(b), PPMMathInvalidMulPPM(a, b)); return (a * b) / MAX_PPM; } @@ -20,9 +18,7 @@ library PPMMath { // to prevent curation fees from rounding down to zero // a must be in ppm function mulPPMRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { - if (!isValidPPM(b)) { - revert PPMMathInvalidPPM(b); - } + require(isValidPPM(b), PPMMathInvalidPPM(b)); return a - mulPPM(MAX_PPM - b, a); } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index cb0123e32..ea7ef45c8 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -52,9 +52,7 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora uint256 delegationFeeCut = _graphStaking().getDelegationFeeCut(receiver, dataService, paymentType); uint256 tokensDelegationPool = tokens.mulPPM(delegationFeeCut); uint256 totalCut = tokensProtocol + tokensDataService + tokensDelegationPool; - if (totalCut > tokens) { - revert GraphPaymentsInsufficientTokens(tokens, totalCut); - } + require(tokens >= totalCut, GraphPaymentsInsufficientTokens(tokens, totalCut)); // Pay protocol cut _graphToken().burnTokens(tokensProtocol); diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 507c79393..19274123a 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -38,13 +38,14 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { uint256 revokeCollectorThawingPeriod, uint256 withdrawEscrowThawingPeriod ) GraphDirectory(controller) { - if (revokeCollectorThawingPeriod > MAX_THAWING_PERIOD) { - revert PaymentsEscrowThawingPeriodTooLong(revokeCollectorThawingPeriod, MAX_THAWING_PERIOD); - } - - if (withdrawEscrowThawingPeriod > MAX_THAWING_PERIOD) { - revert PaymentsEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD); - } + require( + revokeCollectorThawingPeriod <= MAX_THAWING_PERIOD, + PaymentsEscrowThawingPeriodTooLong(revokeCollectorThawingPeriod, MAX_THAWING_PERIOD) + ); + require( + withdrawEscrowThawingPeriod <= MAX_THAWING_PERIOD, + PaymentsEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD) + ); REVOKE_COLLECTOR_THAWING_PERIOD = revokeCollectorThawingPeriod; WITHDRAW_ESCROW_THAWING_PERIOD = withdrawEscrowThawingPeriod; @@ -53,9 +54,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // approve a data service to collect funds function approveCollector(address dataService, uint256 tokens) external { Collector storage collector = authorizedCollectors[msg.sender][dataService]; - if (collector.allowance > tokens) { - revert PaymentsEscrowInsufficientAllowance(collector.allowance, tokens); - } + require(tokens > collector.allowance, PaymentsEscrowInconsistentAllowance(collector.allowance, tokens)); collector.authorized = true; collector.allowance = tokens; @@ -72,9 +71,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // cancel thawing a data service's collector authorization function cancelThawCollector(address dataService) external { - if (authorizedCollectors[msg.sender][dataService].thawEndTimestamp == 0) { - revert PaymentsEscrowNotThawing(); - } + require(authorizedCollectors[msg.sender][dataService].thawEndTimestamp != 0, PaymentsEscrowNotThawing()); authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; emit CancelThawCollector(msg.sender, dataService); @@ -84,13 +81,11 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { function revokeCollector(address dataService) external { Collector storage collector = authorizedCollectors[msg.sender][dataService]; - if (collector.thawEndTimestamp == 0) { - revert PaymentsEscrowNotThawing(); - } - - if (collector.thawEndTimestamp > block.timestamp) { - revert PaymentsEscrowStillThawing(block.timestamp, collector.thawEndTimestamp); - } + require(collector.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); + require( + collector.thawEndTimestamp < block.timestamp, + PaymentsEscrowStillThawing(block.timestamp, collector.thawEndTimestamp) + ); delete authorizedCollectors[msg.sender][dataService]; emit RevokeCollector(msg.sender, dataService); @@ -110,9 +105,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // if amount thawing is zero and requested amount is zero this is an invalid request. // otherwise if amount thawing is greater than zero and requested amount is zero this // is a cancel thaw request. - if (account.tokensThawing == 0) { - revert PaymentsEscrowInsufficientTokensThawing(); - } + require(account.tokensThawing != 0, PaymentsEscrowInsufficientTokensThawing()); account.tokensThawing = 0; account.thawEndTimestamp = 0; emit CancelThaw(msg.sender, receiver); @@ -120,9 +113,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // Check if the escrow balance is sufficient - if (account.balance < tokens) { - revert PaymentsEscrowInsufficientBalance(account.balance, tokens); - } + require(account.balance >= tokens, PaymentsEscrowInsufficientBalance(account.balance, tokens)); // Set amount to thaw account.tokensThawing = tokens; @@ -135,16 +126,11 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // Withdraws all thawed escrow from a receiver's escrow account function withdraw(address receiver) external { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; - if (account.thawEndTimestamp == 0) { - revert PaymentsEscrowNotThawing(); - } - - if (account.thawEndTimestamp > block.timestamp) { - revert PaymentsEscrowStillThawing({ - currentTimestamp: block.timestamp, - thawEndTimestamp: account.thawEndTimestamp - }); - } + require(account.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); + require( + account.thawEndTimestamp < block.timestamp, + PaymentsEscrowStillThawing(block.timestamp, account.thawEndTimestamp) + ); // Amount is the minimum between the amount being thawed and the actual balance uint256 tokens = account.tokensThawing > account.balance ? account.balance : account.tokensThawing; @@ -167,14 +153,8 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { ) external { // Check if collector is authorized and has enough funds Collector storage collector = authorizedCollectors[payer][msg.sender]; - - if (!collector.authorized) { - revert PaymentsEscrowCollectorNotAuthorized(payer, msg.sender); - } - - if (collector.allowance < tokens) { - revert PaymentsEscrowInsufficientAllowance(collector.allowance, tokens); - } + require(collector.authorized, PaymentsEscrowCollectorNotAuthorized(payer, msg.sender)); + require(collector.allowance >= tokens, PaymentsEscrowInsufficientAllowance(collector.allowance, tokens)); // Reduce amount from approved collector collector.allowance -= tokens; @@ -182,9 +162,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // Collect tokens from PaymentsEscrow up to amount available EscrowAccount storage account = escrowAccounts[payer][receiver]; uint256 availableTokens = account.balance - account.tokensThawing; - if (availableTokens < tokens) { - revert PaymentsEscrowInsufficientBalance(availableTokens, tokens); - } + require(availableTokens >= tokens, PaymentsEscrowInsufficientBalance(availableTokens, tokens)); account.balance -= tokens; @@ -195,9 +173,10 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { _graphPayments().collect(paymentType, receiver, tokens, dataService, tokensDataService); uint256 balanceAfter = _graphToken().balanceOf(address(this)); - if (balanceBefore - balanceAfter != tokens) { - revert PaymentsEscrowInconsistentCollection(balanceBefore, balanceAfter, tokens); - } + require( + balanceBefore == tokens + balanceAfter, + PaymentsEscrowInconsistentCollection(balanceBefore, balanceAfter, tokens) + ); emit EscrowCollected(payer, receiver, tokens); } diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index 6c50f8015..b535a72de 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -41,10 +41,10 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { */ function collect(IGraphPayments.PaymentTypes paymentType, bytes memory data) external returns (uint256) { (SignedRAV memory signedRAV, uint256 dataServiceCut) = abi.decode(data, (SignedRAV, uint256)); - - if (signedRAV.rav.dataService != msg.sender) { - revert TAPCollectorCallerNotDataService(msg.sender, signedRAV.rav.dataService); - } + require( + signedRAV.rav.dataService == msg.sender, + TAPCollectorCallerNotDataService(msg.sender, signedRAV.rav.dataService) + ); address dataService = signedRAV.rav.dataService; address payer = _recoverRAVSigner(signedRAV); @@ -52,9 +52,10 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { uint256 tokensRAV = signedRAV.rav.valueAggregate; uint256 tokensAlreadyCollected = tokensCollected[dataService][receiver][payer]; - if (tokensRAV < tokensAlreadyCollected) { - revert TAPCollectorInconsistentRAVTokens(tokensRAV, tokensAlreadyCollected); - } + require( + tokensRAV > tokensAlreadyCollected, + TAPCollectorInconsistentRAVTokens(tokensRAV, tokensAlreadyCollected) + ); uint256 tokensToCollect = tokensRAV - tokensAlreadyCollected; uint256 tokensDataService = tokensToCollect.mulPPM(dataServiceCut); diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 16367b776..1e81e7ad2 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -45,9 +45,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address private immutable STAKING_EXTENSION_ADDRESS; modifier onlyAuthorized(address serviceProvider, address verifier) { - if (!_isAuthorized(msg.sender, serviceProvider, verifier)) { - revert HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier); - } + require( + _isAuthorized(msg.sender, serviceProvider, verifier), + HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier) + ); _; } @@ -66,7 +67,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { */ // solhint-disable-next-line payable-fallback, no-complex-fallback fallback() external { - //require(_implementation() != address(0), "only through proxy"); address extensionImpl = STAKING_EXTENSION_ADDRESS; // solhint-disable-next-line no-inline-assembly assembly { @@ -205,16 +205,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, uint256 tokens ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) returns (bytes32) { - if (tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } + require(tokens != 0, HorizonStakingInvalidZeroTokens()); + Provision storage prov = _provisions[serviceProvider][verifier]; ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; bytes32 thawRequestId = keccak256(abi.encodePacked(serviceProvider, verifier, sp.nextThawRequestNonce)); sp.nextThawRequestNonce += 1; ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - require(_getProviderTokensAvailable(serviceProvider, verifier) >= tokens, "insufficient tokens available"); + uint256 tokensAvailable = _getProviderTokensAvailable(serviceProvider, verifier); + require(tokensAvailable >= tokens, HorizonStakingInsufficientTokensAvailable(tokensAvailable, tokens)); prov.tokensThawing = prov.tokensThawing + tokens; if (prov.sharesThawing == 0) { @@ -226,9 +226,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { thawRequest.thawingUntil = uint64(block.timestamp + uint256(prov.thawingPeriod)); prov.sharesThawing = prov.sharesThawing + thawRequest.shares; - if (prov.nThawRequests >= MAX_THAW_REQUESTS) { - revert HorizonStakingTooManyThawRequests(); - } + require(prov.nThawRequests < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); if (prov.nThawRequests == 0) { prov.firstThawRequestId = thawRequestId; } else { @@ -244,10 +242,11 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // moves thawed stake from a provision back into the provider's available stake function deprovision(address serviceProvider, address verifier, uint256 tokens) external override notPartialPaused { - require(_isAuthorized(msg.sender, serviceProvider, verifier), "!auth"); - if (tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } + require( + _isAuthorized(msg.sender, serviceProvider, verifier), + HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier) + ); + require(tokens != 0, HorizonStakingInvalidZeroTokens()); _fulfillThawRequests(serviceProvider, verifier, tokens); } @@ -323,9 +322,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, uint256 tokens ) external override notPartialPaused { - if (tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } + require(tokens != 0, HorizonStakingInvalidZeroTokens()); DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); pool.tokens = pool.tokens + tokens; emit TokensToDelegationPoolAdded(serviceProvider, verifier, tokens); @@ -349,7 +346,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 sharesThawing = pool.sharesThawing; uint256 tokensThawing = pool.tokensThawing; - require(delegation.nThawRequests > 0, "no thaw requests"); + require(delegation.nThawRequests > 0, HorizonStakingNothingThawing()); bytes32 thawRequestId = delegation.firstThawRequestId; while (thawRequestId != bytes32(0)) { ThawRequest storage thawRequest = _thawRequests[thawRequestId]; @@ -431,14 +428,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { ) external override notPartialPaused { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; - if (prov.tokens < tokens) { - revert HorizonStakingInsufficientTokens(tokens, prov.tokens); - } + require(prov.tokens >= tokens, HorizonStakingInsufficientTokens(prov.tokens, tokens)); uint256 tokensToSlash = tokens; uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); if (providerTokensSlashed > 0) { - require(prov.tokens.mulPPM(prov.maxVerifierCut) >= tokensVerifier, "verifier cut too high"); + uint256 maxVerifierCut = prov.tokens.mulPPM(prov.maxVerifierCut); + require( + maxVerifierCut >= tokensVerifier, + HorizonStakingVerifierTokensTooHigh(tokensVerifier, maxVerifierCut) + ); if (tokensVerifier > 0) { _graphToken().pushTokens(verifierDestination, tokensVerifier); emit VerifierTokensSent(serviceProvider, verifier, verifierDestination, tokensVerifier); @@ -463,7 +462,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { if (tokensToSlash > 0) { DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); if (delegationSlashingEnabled) { - require(pool.tokens >= tokensToSlash, "insufficient delegated tokens"); + require(pool.tokens >= tokensToSlash, HorizonStakingNotEnoughDelegation(pool.tokens, tokensToSlash)); _graphToken().burnTokens(tokensToSlash); uint256 delegationFractionSlashed = (tokensToSlash * FIXED_POINT_PRECISION) / pool.tokens; pool.tokens = pool.tokens - tokensToSlash; @@ -500,15 +499,13 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 maxVerifierCut, uint64 thawingPeriod ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { - if (!_allowedLockedVerifiers[verifier]) { - revert HorizonStakingVerifierNotAllowed(verifier); - } + require(_allowedLockedVerifiers[verifier], HorizonStakingVerifierNotAllowed(verifier)); _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } // for vesting contracts function setOperatorLocked(address operator, address verifier, bool allowed) external override { - if (!_allowedLockedVerifiers[verifier]) revert HorizonStakingVerifierNotAllowed(verifier); + require(_allowedLockedVerifiers[verifier], HorizonStakingVerifierNotAllowed(verifier)); _setOperator(operator, verifier, allowed); } @@ -569,9 +566,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * PRIVATE FUNCTIONS */ function _stakeTo(address _serviceProvider, uint256 _tokens) private { - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } + require(_tokens != 0, HorizonStakingInvalidZeroTokens()); // Transfer tokens to stake from caller to this contract _graphToken().pullTokens(msg.sender, _tokens); @@ -582,12 +577,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { function _unstake(uint256 _tokens) private { address serviceProvider = msg.sender; - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - if (_getIdleStake(serviceProvider) < _tokens) { - revert HorizonStakingInsufficientCapacity(); - } + require(_tokens != 0, HorizonStakingInvalidZeroTokens()); + require(_tokens <= _getIdleStake(serviceProvider), HorizonStakingInsufficientCapacity()); ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; uint256 stakedTokens = sp.tokensStaked; @@ -595,9 +586,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // to cover existing allocations // TODO this is only needed until legacy allocations are closed, // so we should remove it after the transition period - if ((stakedTokens - _tokens) < sp.__DEPRECATED_tokensAllocated) { - revert HorizonStakingInsufficientCapacityForLegacyAllocations(); - } + require( + stakedTokens - _tokens >= sp.__DEPRECATED_tokensAllocated, + HorizonStakingInsufficientCapacityForLegacyAllocations() + ); // This is also only during the transition period: we need // to ensure tokens stay locked after closing legacy allocations. @@ -641,12 +633,17 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 _maxVerifierCut, uint64 _thawingPeriod ) private { - if (_getIdleStake(_serviceProvider) < _tokens) { - revert HorizonStakingInsufficientCapacity(); - } - require(_tokens >= MIN_PROVISION_SIZE, "!tokens"); - require(_maxVerifierCut <= MAX_MAX_VERIFIER_CUT, "maxVerifierCut too high"); - require(_thawingPeriod <= _maxThawingPeriod, "thawingPeriod too high"); + require(_tokens >= MIN_PROVISION_SIZE, HorizonStakingInvalidTokens(_tokens, MIN_PROVISION_SIZE)); + require( + _maxVerifierCut <= MAX_MAX_VERIFIER_CUT, + HorizonStakingInvalidMaxVerifierCut(_maxVerifierCut, MAX_MAX_VERIFIER_CUT) + ); + require( + _thawingPeriod <= _maxThawingPeriod, + HorizonStakingInvalidThawingPeriod(_thawingPeriod, _maxThawingPeriod) + ); + require(_tokens <= _getIdleStake(_serviceProvider), HorizonStakingInsufficientCapacity()); + _provisions[_serviceProvider][_verifier] = Provision({ tokens: _tokens, tokensThawing: 0, @@ -669,15 +666,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { function _addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) private { Provision storage prov = _provisions[_serviceProvider][_verifier]; - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } - if (prov.createdAt == 0) { - revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); - } - if (_getIdleStake(_serviceProvider) < _tokens) { - revert HorizonStakingInsufficientCapacity(); - } + require(_tokens != 0, HorizonStakingInvalidZeroTokens()); + require(prov.createdAt != 0, HorizonStakingInvalidProvision(_serviceProvider, _verifier)); + require(_tokens <= _getIdleStake(_serviceProvider), HorizonStakingInsufficientCapacity()); prov.tokens = prov.tokens + _tokens; _serviceProviders[_serviceProvider].tokensProvisioned = @@ -694,8 +685,11 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // Get tokens available for withdraw and update balance ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; - require(tokensToWithdraw > 0, "!tokens"); - require(block.number >= sp.__DEPRECATED_tokensLockedUntil, "locked"); + require(tokensToWithdraw > 0, HorizonStakingInvalidZeroTokens()); + require( + block.timestamp >= sp.__DEPRECATED_tokensLockedUntil, + HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) + ); // Reset locked tokens sp.__DEPRECATED_tokensLocked = 0; @@ -710,25 +704,21 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) private { - if (_tokens == 0) { - revert HorizonStakingInvalidZeroTokens(); - } + require(_tokens != 0, HorizonStakingInvalidZeroTokens()); + // TODO: remove this after L2 transfer tool for delegation is removed - if (_tokens < MIN_DELEGATION) { - revert HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens); - } - if (_provisions[_serviceProvider][_verifier].tokens == 0) { - revert HorizonStakingInvalidProvision(_serviceProvider, _verifier); - } + require(_tokens >= MIN_DELEGATION, HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens)); + require( + _provisions[_serviceProvider][_verifier].tokens != 0, + HorizonStakingInvalidProvision(_serviceProvider, _verifier) + ); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); Delegation storage delegation = pool.delegators[msg.sender]; // Calculate shares to issue uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); - if (shares == 0 || shares < _minSharesOut) { - revert HorizonStakingSlippageProtection(_minSharesOut, shares); - } + require(shares != 0 && shares >= _minSharesOut, HorizonStakingSlippageProtection(_minSharesOut, shares)); pool.tokens = pool.tokens + _tokens; pool.shares = pool.shares + shares; @@ -739,10 +729,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } function _undelegate(address _serviceProvider, address _verifier, uint256 _shares) private { - require(_shares > 0, "!shares"); + require(_shares > 0, HorizonStakingInvalidZeroShares()); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); Delegation storage delegation = pool.delegators[msg.sender]; - require(delegation.shares >= _shares, "!shares-avail"); + require(delegation.shares >= _shares, HorizonStakingInvalidSharesAmount(delegation.shares, _shares)); uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; @@ -756,7 +746,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // TODO: remove this when L2 transfer tools are removed if (delegation.shares != 0) { uint256 remainingTokens = (delegation.shares * (pool.tokens - pool.tokensThawing)) / pool.shares; - require(remainingTokens >= MIN_DELEGATION, "!minimum-delegation"); + require( + remainingTokens >= MIN_DELEGATION, + HorizonStakingInsufficientTokens(remainingTokens, MIN_DELEGATION) + ); } bytes32 thawRequestId = keccak256( abi.encodePacked(_serviceProvider, _verifier, msg.sender, delegation.nextThawRequestNonce) @@ -767,7 +760,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { thawRequest.thawingUntil = uint64( block.timestamp + uint256(_provisions[_serviceProvider][_verifier].thawingPeriod) ); - require(delegation.nThawRequests < MAX_THAW_REQUESTS, "max thaw requests"); + require(delegation.nThawRequests < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); if (delegation.nThawRequests == 0) { delegation.firstThawRequestId = thawRequestId; } else { @@ -792,7 +785,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 sharesThawing = pool.sharesThawing; uint256 tokensThawing = pool.tokensThawing; - require(delegation.nThawRequests > 0, "no thaw requests"); + require(delegation.nThawRequests > 0, HorizonStakingNothingThawing()); bytes32 thawRequestId = delegation.firstThawRequestId; while (thawRequestId != bytes32(0)) { ThawRequest storage thawRequest = _thawRequests[thawRequestId]; @@ -826,7 +819,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } function _setOperator(address _operator, address _verifier, bool _allowed) private { - require(_operator != msg.sender, "operator == sender"); + require(_operator != msg.sender, HorizonStakingCallerIsServiceProvider()); if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { _legacyOperatorAuth[msg.sender][_operator] = _allowed; } else { @@ -841,10 +834,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 sharesThawing = prov.sharesThawing; uint256 tokensThawing = prov.tokensThawing; while (tokensRemaining > 0) { - require(prov.nThawRequests > 0, "not enough thawed tokens"); + require(prov.nThawRequests > 0, HorizonStakingCannotFulfillThawRequest()); bytes32 thawRequestId = prov.firstThawRequestId; ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - require(thawRequest.thawingUntil <= block.timestamp, "thawing period not over"); + require(thawRequest.thawingUntil <= block.timestamp, HorizonStakingStillThawing(thawRequest.thawingUntil)); uint256 thawRequestTokens = (thawRequest.shares * tokensThawing) / sharesThawing; if (thawRequestTokens <= tokensRemaining) { tokensRemaining = tokensRemaining - thawRequestTokens; diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index de3a08214..87e2f3ed0 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -23,12 +23,17 @@ abstract contract Managed is GraphDirectory { /// @dev Gap for future storage variables uint256[10] private __gap; + error ManagedIsPaused(); + error ManagedIsPartialPaused(); + error ManagedOnlyController(); + error ManagedOnlyGovernor(); + /** * @dev Revert if the controller is paused or partially paused */ modifier notPartialPaused() { - require(!_graphController().paused(), "Paused"); - require(!_graphController().partialPaused(), "Partial-paused"); + require(!_graphController().paused(), ManagedIsPaused()); + require(!_graphController().partialPaused(), ManagedIsPartialPaused()); _; } @@ -36,7 +41,7 @@ abstract contract Managed is GraphDirectory { * @dev Revert if the controller is paused */ modifier notPaused() { - require(!_graphController().paused(), "Paused"); + require(!_graphController().paused(), ManagedIsPaused()); _; } @@ -44,7 +49,7 @@ abstract contract Managed is GraphDirectory { * @dev Revert if the caller is not the Controller */ modifier onlyController() { - require(msg.sender == address(_graphController()), "Caller must be Controller"); + require(msg.sender == address(_graphController()), ManagedOnlyController()); _; } @@ -52,7 +57,7 @@ abstract contract Managed is GraphDirectory { * @dev Revert if the caller is not the governor */ modifier onlyGovernor() { - require(msg.sender == _graphController().getGovernor(), "Only Controller governor"); + require(msg.sender == _graphController().getGovernor(), ManagedOnlyGovernor()); _; } diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 536fe187d..ed6545593 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -50,31 +50,22 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @dev Check if the caller is the arbitrator. */ modifier onlyArbitrator() { - if (msg.sender != arbitrator) { - revert DisputeManagerNotArbitrator(); - } + require(msg.sender == arbitrator, DisputeManagerNotArbitrator()); _; } modifier onlyPendingDispute(bytes32 disputeId) { - if (!isDisputeCreated(disputeId)) { - revert DisputeManagerInvalidDispute(disputeId); - } - - if (disputes[disputeId].status != IDisputeManager.DisputeStatus.Pending) { - revert DisputeManagerInvalidDisputeStatus(disputes[disputeId].status); - } + require(isDisputeCreated(disputeId), DisputeManagerInvalidDispute(disputeId)); + require( + disputes[disputeId].status == IDisputeManager.DisputeStatus.Pending, + DisputeManagerDisputeNotPending(disputes[disputeId].status) + ); _; } modifier onlyFisherman(bytes32 disputeId) { - if (!isDisputeCreated(disputeId)) { - revert DisputeManagerInvalidDispute(disputeId); - } - - if (msg.sender != disputes[disputeId].fisherman) { - revert DisputeManagerNotFisherman(); - } + require(isDisputeCreated(disputeId), DisputeManagerInvalidDispute(disputeId)); + require(msg.sender == disputes[disputeId].fisherman, DisputeManagerNotFisherman()); _; } @@ -165,16 +156,17 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM Attestation.State memory attestation2 = Attestation.parse(attestationData2); // Test that attestations are conflicting - if (!Attestation.areConflicting(attestation2, attestation1)) { - revert DisputeManagerNonConflictingAttestations( + require( + Attestation.areConflicting(attestation1, attestation2), + DisputeManagerNonConflictingAttestations( attestation1.requestCID, attestation1.responseCID, attestation1.subgraphDeploymentId, attestation2.requestCID, attestation2.responseCID, attestation2.subgraphDeploymentId - ); - } + ) + ); // Create the disputes // The deposit is zero for conflicting attestations @@ -252,9 +244,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM Dispute storage dispute = disputes[disputeId]; // Check if dispute period has finished - if (block.timestamp <= dispute.createdAt + disputePeriod) { - revert DisputeManagerDisputePeriodNotFinished(); - } + require(dispute.createdAt + disputePeriod < block.timestamp, DisputeManagerDisputePeriodNotFinished()); // Return deposit to the fisherman _graphToken().pushTokens(dispute.fisherman, dispute.deposit); @@ -366,9 +356,10 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM dispute.status = IDisputeManager.DisputeStatus.Rejected; // For conflicting disputes, the related dispute must be accepted - if (_isDisputeInConflict(dispute)) { - revert DisputeManagerMustAcceptRelatedDispute(disputeId, dispute.relatedDisputeId); - } + require( + !_isDisputeInConflict(dispute), + DisputeManagerMustAcceptRelatedDispute(disputeId, dispute.relatedDisputeId) + ); // Burn the fisherman's deposit _graphToken().burnTokens(dispute.deposit); @@ -386,15 +377,11 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM address allocationId = _recoverSigner(attestation); Allocation.State memory alloc = subgraphService.getAllocation(allocationId); - if (alloc.indexer == address(0)) { - revert DisputeManagerIndexerNotFound(allocationId); - } - if (alloc.subgraphDeploymentId != attestation.subgraphDeploymentId) { - revert DisputeManagerNonMatchingSubgraphDeployment( - alloc.subgraphDeploymentId, - attestation.subgraphDeploymentId - ); - } + require(alloc.indexer != address(0), DisputeManagerIndexerNotFound(allocationId)); + require( + alloc.subgraphDeploymentId == attestation.subgraphDeploymentId, + DisputeManagerNonMatchingSubgraphDeployment(alloc.subgraphDeploymentId, attestation.subgraphDeploymentId) + ); return alloc.indexer; } @@ -429,9 +416,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM // The indexer is disputable IHorizonStaking.Provision memory provision = _graphStaking().getProvision(indexer, address(subgraphService)); - if (provision.tokens == 0) { - revert DisputeManagerZeroTokens(); - } + require(provision.tokens != 0, DisputeManagerZeroTokens()); // Create a disputeId bytes32 disputeId = keccak256( @@ -445,9 +430,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM ); // Only one dispute for a (indexer, subgraphDeploymentId) at a time - if (isDisputeCreated(disputeId)) { - revert DisputeManagerDisputeAlreadyCreated(disputeId); - } + require(!isDisputeCreated(disputeId), DisputeManagerDisputeAlreadyCreated(disputeId)); // Store dispute disputes[disputeId] = Dispute( @@ -487,22 +470,16 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM bytes32 disputeId = keccak256(abi.encodePacked(_allocationId)); // Only one dispute for an allocationId at a time - if (isDisputeCreated(disputeId)) { - revert DisputeManagerDisputeAlreadyCreated(disputeId); - } + require(!isDisputeCreated(disputeId), DisputeManagerDisputeAlreadyCreated(disputeId)); // Allocation must exist Allocation.State memory alloc = subgraphService.getAllocation(_allocationId); address indexer = alloc.indexer; - if (indexer == address(0)) { - revert DisputeManagerIndexerNotFound(_allocationId); - } + require(indexer != address(0), DisputeManagerIndexerNotFound(_allocationId)); // The indexer must be disputable IHorizonStaking.Provision memory provision = _graphStaking().getProvision(indexer, address(subgraphService)); - if (provision.tokens == 0) { - revert DisputeManagerZeroTokens(); - } + require(provision.tokens != 0, DisputeManagerZeroTokens()); // Store dispute disputes[disputeId] = Dispute( @@ -556,9 +533,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM */ function _pullSubmitterDeposit(uint256 _deposit) private { // Ensure that fisherman has staked at least the minimum amount - if (_deposit < minimumDeposit) { - revert DisputeManagerInsufficientDeposit(_deposit, minimumDeposit); - } + require(_deposit >= minimumDeposit, DisputeManagerInsufficientDeposit(_deposit, minimumDeposit)); // Transfer tokens to deposit from fisherman to this contract _graphToken().pullTokens(msg.sender, _deposit); @@ -581,13 +556,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM // Get slash amount uint256 maxTokensSlash = uint256(maxSlashingCut).mulPPM(totalProvisionTokens); - if (_tokensSlash == 0) { - revert DisputeManagerInvalidTokensSlash(_tokensSlash); - } - - if (_tokensSlash > maxTokensSlash) { - revert DisputeManagerInvalidTokensSlash(_tokensSlash); - } + require(_tokensSlash != 0 && _tokensSlash <= maxTokensSlash, DisputeManagerInvalidTokensSlash(_tokensSlash)); // Rewards amount can only be extracted from service poriver tokens so // we grab the minimum between the slash amount and indexer's tokens @@ -604,9 +573,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @param _arbitrator The address of the arbitration contract or party */ function _setArbitrator(address _arbitrator) private { - if (_arbitrator == address(0)) { - revert DisputeManagerInvalidZeroAddress(); - } + require(_arbitrator != address(0), DisputeManagerInvalidZeroAddress()); arbitrator = _arbitrator; emit ArbitratorSet(arbitrator); } @@ -617,9 +584,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @param _disputePeriod Dispute period in seconds */ function _setDisputePeriod(uint64 _disputePeriod) private { - if (_disputePeriod == 0) { - revert DisputeManagerDisputePeriodZero(); - } + require(_disputePeriod != 0, DisputeManagerDisputePeriodZero()); disputePeriod = _disputePeriod; emit DisputePeriodSet(disputePeriod); } @@ -630,9 +595,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @param _minimumDeposit The minimum deposit in Graph Tokens */ function _setMinimumDeposit(uint256 _minimumDeposit) private { - if (_minimumDeposit == 0) { - revert DisputeManagerInvalidMinimumDeposit(_minimumDeposit); - } + require(_minimumDeposit != 0, DisputeManagerInvalidMinimumDeposit(_minimumDeposit)); minimumDeposit = _minimumDeposit; emit MinimumDepositSet(minimumDeposit); } @@ -644,9 +607,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM */ function _setFishermanRewardCut(uint32 _fishermanRewardCut) private { // Must be within 0% to 100% (inclusive) - if (!PPMMath.isValidPPM(_fishermanRewardCut)) { - revert DisputeManagerInvalidFishermanReward(_fishermanRewardCut); - } + require(PPMMath.isValidPPM(_fishermanRewardCut), DisputeManagerInvalidFishermanReward(_fishermanRewardCut)); fishermanRewardCut = _fishermanRewardCut; emit FishermanRewardCutSet(fishermanRewardCut); } @@ -657,9 +618,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM */ function _setMaxSlashingCut(uint32 _maxSlashingCut) private { // Must be within 0% to 100% (inclusive) - if (!PPMMath.isValidPPM(_maxSlashingCut)) { - revert DisputeManagerInvalidMaxSlashingCut(_maxSlashingCut); - } + require(PPMMath.isValidPPM(_maxSlashingCut), DisputeManagerInvalidMaxSlashingCut(_maxSlashingCut)); maxSlashingCut = _maxSlashingCut; emit MaxSlashingCutSet(maxSlashingCut); } @@ -670,9 +629,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @param _subgraphService The address of the subgraph service contract */ function _setSubgraphService(address _subgraphService) private { - if (_subgraphService == address(0)) { - revert DisputeManagerInvalidZeroAddress(); - } + require(_subgraphService != address(0), DisputeManagerInvalidZeroAddress()); subgraphService = ISubgraphService(_subgraphService); emit SubgraphServiceSet(_subgraphService); } diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 302e350bb..9a66c7916 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -36,9 +36,7 @@ contract SubgraphService is using Allocation for mapping(address => Allocation.State); modifier onlyRegisteredIndexer(address indexer) { - if (indexers[indexer].registeredAt == 0) { - revert SubgraphServiceIndexerNotRegistered(indexer); - } + require(indexers[indexer].registeredAt != 0, SubgraphServiceIndexerNotRegistered(indexer)); _; } @@ -77,19 +75,11 @@ contract SubgraphService is (string, string, address) ); - // Must provide a URL - if (bytes(url).length == 0) { - revert SubgraphServiceEmptyUrl(); - } - - // Only allow registering once - if (indexers[indexer].registeredAt != 0) { - revert SubgraphServiceIndexerAlreadyRegistered(); - } + require(bytes(url).length > 0, SubgraphServiceEmptyUrl()); + require(indexers[indexer].registeredAt == 0, SubgraphServiceIndexerAlreadyRegistered()); // Register the indexer indexers[indexer] = Indexer({ registeredAt: block.timestamp, url: url, geoHash: geohash }); - if (rewardsDestination != address(0)) { _setRewardsDestination(indexer, rewardsDestination); } @@ -239,9 +229,10 @@ contract SubgraphService is ); uint256 tokensDataService = tokensCollected.mulPPM(totalCut); uint256 balanceAfter = _graphToken().balanceOf(address(this)); - if (balanceAfter - balanceBefore != tokensDataService) { - revert SubgraphServiceInconsistentCollection(balanceBefore, balanceAfter, tokensDataService); - } + require( + balanceBefore + tokensDataService == balanceAfter, + SubgraphServiceInconsistentCollection(balanceBefore, balanceAfter, tokensDataService) + ); uint256 tokensCurators = 0; uint256 tokensSubgraphService = 0; diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index f6c9a1c56..a72956a29 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -115,7 +115,7 @@ interface IDisputeManager { error DisputeManagerInvalidFishermanReward(uint32 cut); error DisputeManagerInvalidMaxSlashingCut(uint32 maxSlashingCut); error DisputeManagerInvalidTokensSlash(uint256 tokensSlash); - error DisputeManagerInvalidDisputeStatus(IDisputeManager.DisputeStatus status); + error DisputeManagerDisputeNotPending(IDisputeManager.DisputeStatus status); error DisputeManagerInsufficientDeposit(uint256 deposit, uint256 minimumDeposit); error DisputeManagerDisputeAlreadyCreated(bytes32 disputeId); error DisputeManagerDisputePeriodNotFinished(); diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index bcbc666e6..34c876135 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -28,7 +28,7 @@ library Allocation { uint256 tokens, uint256 accRewardsPerAllocatedToken ) internal returns (State memory) { - if (self[allocationId].exists()) revert AllocationAlreadyExists(allocationId); + require(!self[allocationId].exists(), AllocationAlreadyExists(allocationId)); State memory allocation = State({ indexer: indexer, @@ -50,8 +50,7 @@ library Allocation { // For stale POIs this ensures the rewards are not collected with the next valid POI function presentPOI(mapping(address => State) storage self, address allocationId) internal returns (State memory) { State storage allocation = _get(self, allocationId); - if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); - if (allocation.isAltruistic()) revert AllocationZeroTokens(allocationId); + require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.lastPOIPresentedAt = block.timestamp; return allocation; @@ -63,7 +62,7 @@ library Allocation { uint256 accRewardsPerAllocatedToken ) internal returns (State memory) { State storage allocation = _get(self, allocationId); - if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); + require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; return allocation; @@ -74,7 +73,7 @@ library Allocation { address allocationId ) internal returns (State memory) { State storage allocation = _get(self, allocationId); - if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); + require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.accRewardsPending = 0; return allocation; @@ -82,7 +81,7 @@ library Allocation { function close(mapping(address => State) storage self, address allocationId) internal returns (State memory) { State storage allocation = _get(self, allocationId); - if (!allocation.isOpen()) revert AllocationClosed(allocationId, allocation.closedAt); + require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.closedAt = block.timestamp; return allocation; @@ -106,7 +105,7 @@ library Allocation { function _get(mapping(address => State) storage self, address allocationId) private view returns (State storage) { State storage allocation = self[allocationId]; - if (!allocation.exists()) revert AllocationDoesNotExist(allocationId); + require(allocation.exists(), AllocationDoesNotExist(allocationId)); return allocation; } } diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index 5d5771721..b08802ec3 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -58,9 +58,10 @@ library Attestation { */ function parse(bytes memory _data) internal pure returns (State memory) { // Check attestation data length - if (_data.length != ATTESTATION_SIZE_BYTES) { - revert AttestationInvalidBytesLength(_data.length, ATTESTATION_SIZE_BYTES); - } + require( + _data.length == ATTESTATION_SIZE_BYTES, + AttestationInvalidBytesLength(_data.length, ATTESTATION_SIZE_BYTES) + ); // Decode receipt (bytes32 requestCID, bytes32 responseCID, bytes32 subgraphDeploymentId) = abi.decode( @@ -82,9 +83,10 @@ library Attestation { * @return uint8 value */ function _toUint8(bytes memory _bytes, uint256 _start) private pure returns (uint8) { - if (_bytes.length < (_start + UINT8_BYTE_LENGTH)) { - revert AttestationInvalidBytesLength(_bytes.length, _start + UINT8_BYTE_LENGTH); - } + require( + _bytes.length >= _start + UINT8_BYTE_LENGTH, + AttestationInvalidBytesLength(_bytes.length, _start + UINT8_BYTE_LENGTH) + ); uint8 tempUint; // solhint-disable-next-line no-inline-assembly @@ -100,9 +102,10 @@ library Attestation { * @return bytes32 value */ function _toBytes32(bytes memory _bytes, uint256 _start) private pure returns (bytes32) { - if (_bytes.length < (_start + BYTES32_BYTE_LENGTH)) { - revert AttestationInvalidBytesLength(_bytes.length, _start + BYTES32_BYTE_LENGTH); - } + require( + _bytes.length >= _start + BYTES32_BYTE_LENGTH, + AttestationInvalidBytesLength(_bytes.length, _start + BYTES32_BYTE_LENGTH) + ); bytes32 tempBytes32; // solhint-disable-next-line no-inline-assembly diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol index 840973cbf..604a3bd78 100644 --- a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -19,10 +19,9 @@ library LegacyAllocation { address allocationId, bytes32 subgraphDeploymentID ) internal { - if (self[allocationId].exists()) revert LegacyAllocationAlreadyMigrated(allocationId); + require(!self[allocationId].exists(), LegacyAllocationExists(allocationId)); State memory allocation = State({ indexer: indexer, subgraphDeploymentID: subgraphDeploymentID }); - self[allocationId] = allocation; } @@ -31,7 +30,7 @@ library LegacyAllocation { } function revertIfExists(mapping(address => State) storage self, address allocationId) internal view { - if (self[allocationId].exists()) revert LegacyAllocationExists(allocationId); + require(!self[allocationId].exists(), LegacyAllocationExists(allocationId)); } function exists(State memory self) internal pure returns (bool) { @@ -40,7 +39,7 @@ library LegacyAllocation { function _get(mapping(address => State) storage self, address allocationId) private view returns (State storage) { State storage allocation = self[allocationId]; - if (!allocation.exists()) revert LegacyAllocationDoesNotExist(allocationId); + require(allocation.exists(), LegacyAllocationDoesNotExist(allocationId)); return allocation; } } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 69031bf44..ee0f5f2eb 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -17,6 +17,7 @@ import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManagerV1Storage { using ProvisionTracker for mapping(address => uint256); using Allocation for mapping(address => Allocation.State); + using Allocation for Allocation.State; using LegacyAllocation for mapping(address => LegacyAllocation.State); using PPMMath for uint256; @@ -99,7 +100,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager bytes memory _allocationProof, uint32 _delegationRatio ) internal returns (Allocation.State memory) { - if (_allocationId == address(0)) revert AllocationManagerInvalidAllocationId(); + require(_allocationId != address(0), AllocationManagerInvalidAllocationId()); _verifyAllocationProof(_indexer, _allocationId, _allocationProof); @@ -134,9 +135,12 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager Allocation.State memory allocation = allocations.get(allocationId); - // Mint indexing rewards, 0x00 and stale POIs get no rewards... + // Mint indexing rewards. To qualify: + // - POI must be non-zero + // - POI must not be stale, i.e: older than maxPOIStaleness + // - allocation must not be altruistic (tokens = 0) uint256 timeSinceLastPOI = block.number - Math.max(allocation.createdAt, allocation.lastPOIPresentedAt); - uint256 tokensRewards = (timeSinceLastPOI <= maxPOIStaleness && poi != bytes32(0)) + uint256 tokensRewards = (timeSinceLastPOI <= maxPOIStaleness && poi != bytes32(0) && !allocation.isAltruistic()) ? _graphRewardsManager().takeRewards(allocationId) : 0; @@ -205,11 +209,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager uint32 _delegationRatio ) internal returns (Allocation.State memory) { Allocation.State memory allocation = allocations.get(_allocationId); - - // Exit early if the allocation size is the same - if (_tokens == allocation.tokens) { - revert AllocationManagerAllocationSameSize(_allocationId, _tokens); - } + require(_tokens != allocation.tokens, AllocationManagerAllocationSameSize(_allocationId, _tokens)); // Update provision tracker uint256 oldTokens = allocation.tokens; @@ -223,7 +223,9 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager uint256 accRewardsPerAllocatedToken = _graphRewardsManager().onSubgraphAllocationUpdate( allocation.subgraphDeploymentId ); - uint256 accRewardsPending = accRewardsPerAllocatedToken - allocation.accRewardsPerAllocatedToken; + uint256 accRewardsPending = !allocation.isAltruistic() + ? accRewardsPerAllocatedToken - allocation.accRewardsPerAllocatedToken + : 0; // Update the allocation allocations[_allocationId].tokens = _tokens; @@ -278,7 +280,7 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager function _verifyAllocationProof(address _indexer, address _allocationId, bytes memory _proof) internal view { bytes32 digest = _encodeAllocationProof(_indexer, _allocationId); address signer = ECDSA.recover(digest, _proof); - if (signer != _allocationId) revert AllocationManagerInvalidAllocationProof(signer, _allocationId); + require(signer == _allocationId, AllocationManagerInvalidAllocationProof(signer, _allocationId)); } function _encodeAllocationProof(address _indexer, address _allocationId) internal view returns (bytes32) { diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index 67afaadc5..8bfaee861 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -21,9 +21,10 @@ abstract contract Directory { error DirectoryNotDisputeManager(address caller, address disputeManager); modifier onlyDisputeManager() { - if (msg.sender != address(DISPUTE_MANAGER)) { - revert DirectoryNotDisputeManager(msg.sender, address(DISPUTE_MANAGER)); - } + require( + msg.sender == address(DISPUTE_MANAGER), + DirectoryNotDisputeManager(msg.sender, address(DISPUTE_MANAGER)) + ); _; } From b5cb905cb1fb75897a0341f08ba13850600dfff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 17:39:01 -0300 Subject: [PATCH 071/277] fix: couple fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/staking/HorizonStaking.sol | 26 +++++++++---------- .../contracts/DisputeManager.sol | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 1e81e7ad2..c84260eb8 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -102,7 +102,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice Deposit tokens on the caller's stake. * @param tokens Amount of tokens to stake */ - function stake(uint256 tokens) external override { + function stake(uint256 tokens) external override notPartialPaused { _stakeTo(msg.sender, tokens); } @@ -241,12 +241,11 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } // moves thawed stake from a provision back into the provider's available stake - function deprovision(address serviceProvider, address verifier, uint256 tokens) external override notPartialPaused { - require( - _isAuthorized(msg.sender, serviceProvider, verifier), - HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier) - ); - require(tokens != 0, HorizonStakingInvalidZeroTokens()); + function deprovision( + address serviceProvider, + address verifier, + uint256 tokens + ) external override onlyAuthorized(serviceProvider, verifier) notPartialPaused { _fulfillThawRequests(serviceProvider, verifier, tokens); } @@ -384,25 +383,25 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, IGraphPayments.PaymentTypes paymentType, uint256 feeCut - ) external override { + ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); } // For backwards compatibility, delegates to the subgraph data service // (Note this one doesn't have splippage/rounding protection!) - function delegate(address serviceProvider, uint256 tokens) external { + function delegate(address serviceProvider, uint256 tokens) external notPartialPaused { _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); } // For backwards compatibility, undelegates from the subgraph data service - function undelegate(address serviceProvider, uint256 shares) external { + function undelegate(address serviceProvider, uint256 shares) external notPartialPaused { _undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); } // For backwards compatibility, withdraws delegated tokens from the subgraph data service - function withdrawDelegated(address serviceProvider, address newServiceProvider) external { + function withdrawDelegated(address serviceProvider, address newServiceProvider) external notPartialPaused { _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0); } @@ -504,7 +503,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } // for vesting contracts - function setOperatorLocked(address operator, address verifier, bool allowed) external override { + function setOperatorLocked(address operator, address verifier, bool allowed) external override notPartialPaused { require(_allowedLockedVerifiers[verifier], HorizonStakingVerifierNotAllowed(verifier)); _setOperator(operator, verifier, allowed); } @@ -544,7 +543,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param verifier The verifier / data service on which they'll be allowed to operate * @param allowed Whether the operator is authorized or not */ - function setOperator(address operator, address verifier, bool allowed) external override { + function setOperator(address operator, address verifier, bool allowed) external override notPartialPaused { _setOperator(operator, verifier, allowed); } @@ -829,6 +828,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } function _fulfillThawRequests(address _serviceProvider, address _verifier, uint256 _tokens) private { + require(_tokens != 0, HorizonStakingInvalidZeroTokens()); Provision storage prov = _provisions[_serviceProvider][_verifier]; uint256 tokensRemaining = _tokens; uint256 sharesThawing = prov.sharesThawing; diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index ed6545593..55c8c6622 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -270,7 +270,7 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM * @notice Update the dispute period to `_disputePeriod` in seconds * @param disputePeriod Dispute period in seconds */ - function setDisputePeriod(uint64 disputePeriod) external override { + function setDisputePeriod(uint64 disputePeriod) external override onlyOwner { _setDisputePeriod(disputePeriod); } From 180513ef5d58f4c9a48b8dcc3702bfcd438cc205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 24 May 2024 17:52:20 -0300 Subject: [PATCH 072/277] feat: remove partial pause MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/staking/HorizonStaking.sol | 48 +++++++++---------- .../staking/HorizonStakingExtension.sol | 4 +- .../contracts/staking/utilities/Managed.sol | 10 ---- 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index c84260eb8..95174f626 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -102,7 +102,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice Deposit tokens on the caller's stake. * @param tokens Amount of tokens to stake */ - function stake(uint256 tokens) external override notPartialPaused { + function stake(uint256 tokens) external override notPaused { _stakeTo(msg.sender, tokens); } @@ -111,7 +111,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param serviceProvider Address of the service provider * @param tokens Amount of tokens to stake */ - function stakeTo(address serviceProvider, uint256 tokens) external override notPartialPaused { + function stakeTo(address serviceProvider, uint256 tokens) external override notPaused { _stakeTo(serviceProvider, tokens); } @@ -122,11 +122,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param verifier Address of the verifier * @param tokens Amount of tokens to stake */ - function stakeToProvision( - address serviceProvider, - address verifier, - uint256 tokens - ) external override notPartialPaused { + function stakeToProvision(address serviceProvider, address verifier, uint256 tokens) external override notPaused { _stakeTo(serviceProvider, tokens); _addToProvision(serviceProvider, verifier, tokens); } @@ -172,7 +168,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + ) external override notPaused onlyAuthorized(serviceProvider, verifier) { _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } @@ -188,7 +184,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address verifier, uint256 tokens - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + ) external override notPaused onlyAuthorized(serviceProvider, verifier) { _addToProvision(serviceProvider, verifier, tokens); } @@ -204,7 +200,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address verifier, uint256 tokens - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) returns (bytes32) { + ) external override notPaused onlyAuthorized(serviceProvider, verifier) returns (bytes32) { require(tokens != 0, HorizonStakingInvalidZeroTokens()); Provision storage prov = _provisions[serviceProvider][verifier]; @@ -245,7 +241,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address verifier, uint256 tokens - ) external override onlyAuthorized(serviceProvider, verifier) notPartialPaused { + ) external override onlyAuthorized(serviceProvider, verifier) notPaused { _fulfillThawRequests(serviceProvider, verifier, tokens); } @@ -267,7 +263,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { ) external override - notPartialPaused + notPaused onlyAuthorized(serviceProvider, oldVerifier) onlyAuthorized(serviceProvider, newVerifier) { @@ -280,14 +276,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, uint32 maxVerifierCut, uint64 thawingPeriod - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + ) external override notPaused onlyAuthorized(serviceProvider, verifier) { Provision storage prov = _provisions[serviceProvider][verifier]; prov.maxVerifierCutPending = maxVerifierCut; prov.thawingPeriodPending = thawingPeriod; emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); } - function acceptProvisionParameters(address serviceProvider) external override notPartialPaused { + function acceptProvisionParameters(address serviceProvider) external override notPaused { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; prov.maxVerifierCut = prov.maxVerifierCutPending; @@ -304,7 +300,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, uint256 tokens, uint256 minSharesOut - ) external override notPartialPaused { + ) external override notPaused { _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, verifier, tokens, minSharesOut); } @@ -320,7 +316,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address verifier, uint256 tokens - ) external override notPartialPaused { + ) external override notPaused { require(tokens != 0, HorizonStakingInvalidZeroTokens()); DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); pool.tokens = pool.tokens + tokens; @@ -329,7 +325,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // undelegate tokens from a service provider // the shares are burned and replaced with shares in the thawing pool - function undelegate(address serviceProvider, address verifier, uint256 shares) external override notPartialPaused { + function undelegate(address serviceProvider, address verifier, uint256 shares) external override notPaused { _undelegate(serviceProvider, verifier, shares); } @@ -338,7 +334,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, address newServiceProvider, uint256 minSharesForNewProvider - ) external override notPartialPaused { + ) external override notPaused { DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); Delegation storage delegation = pool.delegators[msg.sender]; uint256 thawedTokens = 0; @@ -383,25 +379,25 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, IGraphPayments.PaymentTypes paymentType, uint256 feeCut - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + ) external override notPaused onlyAuthorized(serviceProvider, verifier) { delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); } // For backwards compatibility, delegates to the subgraph data service // (Note this one doesn't have splippage/rounding protection!) - function delegate(address serviceProvider, uint256 tokens) external notPartialPaused { + function delegate(address serviceProvider, uint256 tokens) external notPaused { _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); } // For backwards compatibility, undelegates from the subgraph data service - function undelegate(address serviceProvider, uint256 shares) external notPartialPaused { + function undelegate(address serviceProvider, uint256 shares) external notPaused { _undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); } // For backwards compatibility, withdraws delegated tokens from the subgraph data service - function withdrawDelegated(address serviceProvider, address newServiceProvider) external notPartialPaused { + function withdrawDelegated(address serviceProvider, address newServiceProvider) external notPaused { _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0); } @@ -424,7 +420,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokens, uint256 tokensVerifier, address verifierDestination - ) external override notPartialPaused { + ) external override notPaused { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; require(prov.tokens >= tokens, HorizonStakingInsufficientTokens(prov.tokens, tokens)); @@ -497,13 +493,13 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod - ) external override notPartialPaused onlyAuthorized(serviceProvider, verifier) { + ) external override notPaused onlyAuthorized(serviceProvider, verifier) { require(_allowedLockedVerifiers[verifier], HorizonStakingVerifierNotAllowed(verifier)); _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } // for vesting contracts - function setOperatorLocked(address operator, address verifier, bool allowed) external override notPartialPaused { + function setOperatorLocked(address operator, address verifier, bool allowed) external override notPaused { require(_allowedLockedVerifiers[verifier], HorizonStakingVerifierNotAllowed(verifier)); _setOperator(operator, verifier, allowed); } @@ -543,7 +539,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param verifier The verifier / data service on which they'll be allowed to operate * @param allowed Whether the operator is authorized or not */ - function setOperator(address operator, address verifier, bool allowed) external override notPartialPaused { + function setOperator(address operator, address verifier, bool allowed) external override notPaused { _setOperator(operator, verifier, allowed); } diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 97fd49500..284d2dbe6 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -61,7 +61,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki address from, uint256 tokens, bytes calldata data - ) external override notPartialPaused onlyL2Gateway { + ) external override notPaused onlyL2Gateway { require(from == _counterpartStakingAddress, "ONLY_L1_STAKING_THROUGH_BRIDGE"); (uint8 code, bytes memory functionData) = abi.decode(data, (uint8, bytes)); @@ -116,7 +116,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki * @param tokens Amount of tokens to collect * @param allocationID Allocation where the tokens will be assigned */ - function collect(uint256 tokens, address allocationID) external override { + function collect(uint256 tokens, address allocationID) external override notPaused { // Allocation identifier validation require(allocationID != address(0), "!alloc"); diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index 87e2f3ed0..d9cbc9980 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -24,19 +24,9 @@ abstract contract Managed is GraphDirectory { uint256[10] private __gap; error ManagedIsPaused(); - error ManagedIsPartialPaused(); error ManagedOnlyController(); error ManagedOnlyGovernor(); - /** - * @dev Revert if the controller is paused or partially paused - */ - modifier notPartialPaused() { - require(!_graphController().paused(), ManagedIsPaused()); - require(!_graphController().partialPaused(), ManagedIsPartialPaused()); - _; - } - /** * @dev Revert if the controller is paused */ From e7c00c1835c2cf757612e248a497fe51c088c465 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Sat, 25 May 2024 01:04:02 -0300 Subject: [PATCH 073/277] chore: add horizon unit tests --- packages/horizon/test/GraphBase.t.sol | 12 +- .../horizon/test/escrow/GraphEscrow.t.sol | 2 +- packages/horizon/test/escrow/collect.t.sol | 8 +- .../horizon/test/payments/GraphPayments.t.sol | 8 +- ...aking.t.sol => HorizonStakingShared.t.sol} | 30 +++- .../horizon/test/staking/HorizonStaking.t.sol | 86 ++++++++++++ .../test/staking/delegation/delegate.t.sol | 42 ++++++ .../test/staking/delegation/undelegate.t.sol | 76 ++++++++++ .../test/staking/delegation/withdraw.t.sol | 72 ++++++++++ .../test/staking/operator/operator.t.sol | 14 ++ .../test/staking/provision/deprovision.t.sol | 98 +++++++++++++ .../test/staking/provision/provision.t.sol | 93 +++++++++++++ .../test/staking/provision/reprovision.t.sol | 131 ++++++++++++++++++ .../horizon/test/staking/slash/slash.t.sol | 87 ++++++++++++ .../horizon/test/staking/stake/stake.t.sol | 29 ++++ .../horizon/test/staking/stake/unstake.t.sol | 74 ++++++++++ packages/horizon/test/staking/thaw/thaw.t.sol | 118 ++++++++++++++++ packages/horizon/test/utils/Constants.sol | 6 + packages/horizon/test/utils/Users.sol | 1 + 19 files changed, 971 insertions(+), 16 deletions(-) rename packages/horizon/test/shared/horizon-staking/{HorizonStaking.t.sol => HorizonStakingShared.t.sol} (64%) create mode 100644 packages/horizon/test/staking/HorizonStaking.t.sol create mode 100644 packages/horizon/test/staking/delegation/delegate.t.sol create mode 100644 packages/horizon/test/staking/delegation/undelegate.t.sol create mode 100644 packages/horizon/test/staking/delegation/withdraw.t.sol create mode 100644 packages/horizon/test/staking/operator/operator.t.sol create mode 100644 packages/horizon/test/staking/provision/deprovision.t.sol create mode 100644 packages/horizon/test/staking/provision/provision.t.sol create mode 100644 packages/horizon/test/staking/provision/reprovision.t.sol create mode 100644 packages/horizon/test/staking/slash/slash.t.sol create mode 100644 packages/horizon/test/staking/stake/stake.t.sol create mode 100644 packages/horizon/test/staking/stake/unstake.t.sol create mode 100644 packages/horizon/test/staking/thaw/thaw.t.sol diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index f657d8b3e..27835c54a 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -54,11 +54,13 @@ abstract contract GraphBaseTest is Test, Constants { indexer: createUser("indexer"), operator: createUser("operator"), gateway: createUser("gateway"), - verifier: createUser("verifier") + verifier: createUser("verifier"), + delegator: createUser("delegator") }); // Deploy protocol contracts deployProtocolContracts(); + setupProtocol(); unpauseProtocol(); // Label contracts @@ -147,11 +149,15 @@ abstract contract GraphBaseTest is Test, Constants { proxyAdmin.upgrade(stakingProxy, address(stakingBase)); proxyAdmin.acceptProxy(stakingBase, stakingProxy); staking = IHorizonStaking(address(stakingProxy)); - vm.stopPrank(); + } + + function setupProtocol() private { + vm.startPrank(users.governor); + staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); } function unpauseProtocol() private { - vm.prank(users.governor); + vm.startPrank(users.governor); controller.setPaused(false); } diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index a98eb3322..70c96466f 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaking.t.sol"; +import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; contract GraphEscrowTest is HorizonStakingSharedTest { diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index d7557353a..04d71252d 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -8,7 +8,10 @@ import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; contract GraphEscrowCollectTest is GraphEscrowTest { - function testCollect_Tokens(uint256 amount, uint256 tokensDataService) public useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { + function testCollect_Tokens( + uint256 amount, + uint256 tokensDataService + ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); @@ -16,10 +19,9 @@ contract GraphEscrowCollectTest is GraphEscrowTest { vm.startPrank(users.gateway); escrow.approveCollector(users.verifier, amount); _depositTokens(amount); - vm.stopPrank(); uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - vm.prank(users.verifier); + vm.startPrank(users.verifier); escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); uint256 indexerBalance = token.balanceOf(users.indexer); diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index e4fa18b97..4449bbdcc 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -5,14 +5,14 @@ import "forge-std/Test.sol"; import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; -import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaking.t.sol"; +import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; contract GraphPaymentsTest is HorizonStakingSharedTest { function testCollect( uint256 amount, uint256 tokensDataService - ) public useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { + ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); @@ -42,7 +42,11 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { function testCollect_RevertWhen_InsufficientAmount( uint256 amount, uint256 tokensDataService +<<<<<<< HEAD ) public useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { +======= + ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { +>>>>>>> 9fa803b7 (chore: staking tests refactor) vm.assume(tokensDataService <= 10_000_000_000 ether); vm.assume(tokensDataService > amount); diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol similarity index 64% rename from packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol rename to packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 7fd428e40..2ee0d5764 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStaking.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -8,10 +8,24 @@ import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol abstract contract HorizonStakingSharedTest is GraphBaseTest { + modifier useIndexer() { + vm.startPrank(users.indexer); + _; + vm.stopPrank(); + } + + modifier assumeProvisionTokens(uint256 tokens) { + vm.assume(tokens > MIN_PROVISION_SIZE); + vm.assume(tokens <= 10_000_000_000 ether); + _; + } + modifier useProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) { vm.assume(tokens <= 10_000_000_000 ether); - vm.assume(tokens > 1e18); - _createProvision(tokens, maxVerifierCut, thawingPeriod); + vm.assume(tokens > MIN_PROVISION_SIZE); + vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); + vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); + _createProvision(subgraphDataServiceAddress, tokens, maxVerifierCut, thawingPeriod); _; } @@ -28,22 +42,24 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { /* Helpers */ - function _createProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) internal { - vm.startPrank(users.indexer); + function _createProvision( + address dataServiceAddress, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) internal { token.approve(address(staking), tokens); staking.stakeTo(users.indexer, tokens); staking.provision( users.indexer, - subgraphDataServiceAddress, + dataServiceAddress, tokens, maxVerifierCut, thawingPeriod ); - vm.stopPrank(); } function _setDelegationFeeCut(IGraphPayments.PaymentTypes paymentType, uint256 cut) internal { - vm.prank(users.indexer); staking.setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, cut); } } diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol new file mode 100644 index 000000000..431ce0296 --- /dev/null +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { IHorizonStakingTypes } from "../../contracts/interfaces/IHorizonStakingTypes.sol"; +import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; + +contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { + + modifier useOperator() { + vm.startPrank(users.indexer); + staking.setOperator(users.operator, subgraphDataServiceAddress, true); + vm.startPrank(users.operator); + _; + vm.stopPrank(); + } + + modifier useStake(uint256 amount) { + vm.assume(amount > MIN_PROVISION_SIZE); + approve(address(staking), amount); + staking.stake(amount); + _; + } + + modifier useStakeTo(address to, uint256 amount) { + vm.assume(amount > MIN_PROVISION_SIZE); + _stakeTo(to, amount); + _; + } + + modifier useThawRequest(uint256 thawAmount) { + vm.assume(thawAmount > 0); + _createThawRequest(thawAmount); + _; + } + + modifier useThawAndDeprovision(uint256 amount, uint64 thawingPeriod) { + vm.assume(amount > 0); + _createThawRequest(amount); + skip(thawingPeriod + 1); + _deprovision(amount); + _; + } + + modifier useDelegation(uint256 delegationAmount) { + address msgSender; + (, msgSender,) = vm.readCallers(); + vm.assume(delegationAmount > MIN_DELEGATION); + vm.assume(delegationAmount <= 10_000_000_000 ether); + vm.startPrank(users.delegator); + _delegate(delegationAmount); + vm.startPrank(msgSender); + _; + } + + function _stakeTo(address to, uint256 amount) internal { + approve(address(staking), amount); + staking.stakeTo(to, amount); + } + + function _createThawRequest(uint256 thawAmount) internal returns (bytes32) { + return staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + } + + function _deprovision(uint256 amount) internal { + staking.deprovision(users.indexer, subgraphDataServiceAddress, amount); + } + + function _delegate(uint256 amount) internal { + token.approve(address(staking), amount); + staking.delegate(users.indexer, subgraphDataServiceAddress, amount, 0); + } + + function _getDelegation() internal view returns (Delegation memory) { + return staking.getDelegation(users.delegator, users.indexer, subgraphDataServiceAddress); + } + + function _undelegate(uint256 shares) internal { + staking.undelegate(users.indexer, subgraphDataServiceAddress, shares); + } + + function _getDelegationPool() internal view returns (DelegationPool memory) { + return staking.getDelegationPool(users.indexer, subgraphDataServiceAddress); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol new file mode 100644 index 000000000..279c2f7f7 --- /dev/null +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingDelegateTest is HorizonStakingTest { + + function testDelegate_Tokens( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(delegatedTokens, delegationAmount); + } + + function testDelegate_RevertWhen_ZeroTokens( + uint256 amount + ) public useIndexer useProvision(amount, 0, 0) { + vm.startPrank(users.delegator); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + vm.expectRevert(expectedError); + staking.delegate(users.indexer, subgraphDataServiceAddress, 0, 0); + } + + function testDelegate_RevertWhen_BelowMinimum( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) { + vm.startPrank(users.delegator); + delegationAmount = bound(delegationAmount, 1, MIN_DELEGATION - 1); + token.approve(address(staking), delegationAmount); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientTokens(uint256,uint256)", + MIN_DELEGATION, + delegationAmount + ); + vm.expectRevert(expectedError); + staking.delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol new file mode 100644 index 000000000..73c7a913e --- /dev/null +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingUndelegateTest is HorizonStakingTest { + + function testUndelegate_Tokens( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + // TODO: maybe create a changePrank + vm.stopPrank(); + vm.startPrank(users.delegator); + Delegation memory delegation = _getDelegation(); + _undelegate(delegation.shares); + + Delegation memory thawingDelegation = _getDelegation(); + ThawRequest memory thawRequest = staking.getThawRequest(thawingDelegation.lastThawRequestId); + + assertEq(thawRequest.shares, delegation.shares); + } + + function testUndelegate_RevertWhen_ZeroTokens( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + // TODO: maybe create a changePrank + vm.stopPrank(); + vm.startPrank(users.delegator); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + vm.expectRevert(expectedError); + _undelegate(0); + } + + function testUndelegate_RevertWhen_OverUndelegation( + uint256 amount, + uint256 delegationAmount, + uint256 overDelegationShares + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + // TODO: maybe create a changePrank + vm.stopPrank(); + vm.startPrank(users.delegator); + Delegation memory delegation = _getDelegation(); + vm.assume(overDelegationShares > delegation.shares); + + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientTokens(uint256,uint256)", + overDelegationShares, + delegation.shares + ); + vm.expectRevert(expectedError); + _undelegate(overDelegationShares); + } + + function testUndelegate_RevertWhen_UndelegateLeavesInsufficientTokens( + uint256 delegationAmount, + uint256 withdrawShares + ) + public + useIndexer + useProvision(10_000_000 ether, 0, 0) + useDelegation(delegationAmount) + { + // TODO: maybe create a changePrank + vm.stopPrank(); + vm.startPrank(users.delegator); + uint256 minShares = delegationAmount - MIN_DELEGATION + 1; + withdrawShares = bound(withdrawShares, minShares, delegationAmount - 1); + + vm.expectRevert("!minimum-delegation"); + _undelegate(withdrawShares); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol new file mode 100644 index 000000000..593a2dae5 --- /dev/null +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { + + modifier useUndelegate(uint256 shares) { + vm.stopPrank(); + vm.startPrank(users.delegator); + Delegation memory delegation = _getDelegation(); + shares = bound(shares, 1, delegation.shares); + + if (shares != delegation.shares) { + DelegationPool memory pool = _getDelegationPool(); + uint256 tokens = (shares * (pool.tokens - pool.tokensThawing)) / pool.shares; + uint256 newTokensThawing = pool.tokensThawing + tokens; + uint256 remainingTokens = (delegation.shares * (pool.tokens - newTokensThawing)) / pool.shares; + vm.assume(remainingTokens >= MIN_DELEGATION); + } + + _undelegate(shares); + _; + } + + function _withdrawDelegated() private { + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0x0), 0); + } + + function _expectedTokensFromThawRequest(ThawRequest memory thawRequest) private view returns (uint256) { + DelegationPool memory pool = _getDelegationPool(); + return (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing; + } + + function testWithdrawDelegation_Tokens( + uint256 delegationAmount, + uint256 withdrawShares + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(withdrawShares) + { + Delegation memory thawingDelegation = _getDelegation(); + ThawRequest memory thawRequest = staking.getThawRequest(thawingDelegation.lastThawRequestId); + + skip(thawRequest.thawingUntil + 1); + + uint256 previousBalance = token.balanceOf(users.delegator); + uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest); + _withdrawDelegated(); + + uint256 newBalance = token.balanceOf(users.delegator); + assertEq(newBalance - previousBalance, expectedTokens); + } + + function testWithdrawDelegation_RevertWhen_NotThawing( + uint256 delegationAmount + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + vm.expectRevert(expectedError); + _withdrawDelegated(); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/operator/operator.t.sol b/packages/horizon/test/staking/operator/operator.t.sol new file mode 100644 index 000000000..6fffe0cf3 --- /dev/null +++ b/packages/horizon/test/staking/operator/operator.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingOperatorTest is HorizonStakingTest { + + function testOperator_SetOperator() public useIndexer { + staking.setOperator(users.operator, subgraphDataServiceAddress, true); + assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol new file mode 100644 index 000000000..3afb3a7b1 --- /dev/null +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingDeprovisionTest is HorizonStakingTest { + + function testDeprovision_Tokens( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + skip(thawingPeriod + 1); + + _deprovision(amount); + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, amount); + } + + function testDeprovision_OperatorMovingTokens( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useOperator useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + skip(thawingPeriod + 1); + + _deprovision(amount); + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, amount); + } + + function testDeprovision_RevertWhen_OperatorNotAuthorized( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + vm.startPrank(users.operator); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingNotAuthorized(address,address,address)", + users.operator, + users.indexer, + subgraphDataServiceAddress + ); + vm.expectRevert(expectedError); + _deprovision(amount); + } + + function testDeprovision_RevertWhen_ZeroTokens( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + vm.expectRevert(expectedError); + _deprovision(0); + } + + function testDeprovision_RevertWhen_NoThawingTokens( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + vm.expectRevert(expectedError); + _deprovision(amount); + } + + function testDeprovision_RevertWhen_StillThawing( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + vm.assume(thawingPeriod > 0); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingStillThawing(uint256,uint256)", + block.timestamp, + block.timestamp + thawingPeriod + ); + vm.expectRevert(expectedError); + _deprovision(amount); + } + + function testDeprovision_RevertWhen_NotEnoughThawedTokens( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod, + uint256 deprovisionAmount + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + vm.assume(deprovisionAmount > amount); + skip(thawingPeriod + 1); + + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + vm.expectRevert(expectedError); + _deprovision(deprovisionAmount); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol new file mode 100644 index 000000000..ee9591205 --- /dev/null +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingProvisionTest is HorizonStakingTest { + + function testProvision_Create( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, amount); + } + + function testProvision_RevertWhen_InsufficientTokens(uint256 amount) public useIndexer useStake(1000 ether) { + vm.assume(amount < MIN_PROVISION_SIZE); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientTokens(uint256,uint256)", MIN_PROVISION_SIZE, amount); + vm.expectRevert(expectedError); + staking.provision(users.indexer, subgraphDataServiceAddress, amount, 0, 0); + } + + function testProvision_RevertWhen_MaxVerifierCutTooHigh( + uint256 amount, + uint32 maxVerifierCut + ) public useIndexer useStake(amount) { + vm.assume(amount > MIN_PROVISION_SIZE); + vm.assume(maxVerifierCut > MAX_MAX_VERIFIER_CUT); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingMaxVerifierCutExceeded(uint32,uint32)", MAX_MAX_VERIFIER_CUT, maxVerifierCut); + vm.expectRevert(expectedError); + staking.provision(users.indexer, subgraphDataServiceAddress, amount, maxVerifierCut, 0); + } + + function testProvision_RevertWhen_ThawingPeriodTooHigh( + uint256 amount, + uint64 thawingPeriod + ) public useIndexer useStake(amount) { + vm.assume(amount > MIN_PROVISION_SIZE); + vm.assume(thawingPeriod > MAX_THAWING_PERIOD); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingMaxThawingPeriodExceeded(uint64,uint64)", MAX_THAWING_PERIOD, thawingPeriod); + vm.expectRevert(expectedError); + staking.provision(users.indexer, subgraphDataServiceAddress, amount, 0, thawingPeriod); + } + + function testProvision_RevertWhen_ThereIsNoIdleStake( + uint256 amount, + uint256 provisionTokens + ) public useIndexer useStake(amount) { + vm.assume(amount > MIN_PROVISION_SIZE); + vm.assume(provisionTokens > amount); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); + vm.expectRevert(expectedError); + staking.provision(users.indexer, subgraphDataServiceAddress, provisionTokens, 0, 0); + } + + function testProvision_OperatorAddTokensToProvision( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod, + uint256 tokensToAdd + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + tokensToAdd = bound(tokensToAdd, 1, type(uint256).max - amount); + // Set operator + staking.setOperator(users.operator, subgraphDataServiceAddress, true); + + // Add more tokens to the provision + vm.startPrank(users.operator); + _stakeTo(users.indexer, tokensToAdd); + staking.addToProvision(users.indexer, subgraphDataServiceAddress, tokensToAdd); + + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, amount + tokensToAdd); + } + + function testProvision_RevertWhen_OperatorNotAuthorized( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + vm.startPrank(users.operator); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingNotAuthorized(address,address,address)", + users.operator, + users.indexer, + subgraphDataServiceAddress + ); + vm.expectRevert(expectedError); + staking.provision(users.indexer, subgraphDataServiceAddress, amount, maxVerifierCut, thawingPeriod); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol new file mode 100644 index 000000000..2c10e9060 --- /dev/null +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingReprovisionTest is HorizonStakingTest { + + address private newDataService = makeAddr("newDataService"); + + function _reprovision(uint256 amount) private { + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, amount); + } + + function testReprovision_MovingTokens( + uint64 thawingPeriod, + uint256 provisionAmount + ) + public + useIndexer + useProvision(provisionAmount, 0, thawingPeriod) + useThawRequest(provisionAmount) + { + skip(thawingPeriod + 1); + + _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); + _reprovision(provisionAmount); + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, 0 ether); + + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, newDataService); + assertEq(provisionTokens, provisionAmount + MIN_PROVISION_SIZE); + } + + function testReprovision_OperatorMovingTokens( + uint64 thawingPeriod, + uint256 provisionAmount + ) + public + useOperator + useProvision(provisionAmount, 0, thawingPeriod) + useThawRequest(provisionAmount) + { + skip(thawingPeriod + 1); + + // Switch to indexer to set operator for new data service + vm.startPrank(users.indexer); + staking.setOperator(users.operator, newDataService, true); + + // Switch back to operator + vm.startPrank(users.operator); + _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); + _reprovision(provisionAmount); + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, 0 ether); + + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, newDataService); + assertEq(provisionTokens, provisionAmount + MIN_PROVISION_SIZE); + } + + function testReprovision_RevertWhen_OperatorNotAuthorizedForNewDataService( + uint256 provisionAmount + ) + public + useOperator + useProvision(provisionAmount, 0, 0) + useThawRequest(provisionAmount) + { + // Switch to indexer to create new provision + vm.startPrank(users.indexer); + _createProvision(newDataService, MIN_PROVISION_SIZE, 0, 0); + + // Switch back to operator + vm.startPrank(users.operator); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingNotAuthorized(address,address,address)", + users.operator, + users.indexer, + newDataService + ); + vm.expectRevert(expectedError); + _reprovision(provisionAmount); + } + + function testReprovision_RevertWhen_NoThawingTokens( + uint256 amount + ) public useIndexer useProvision(amount, 0, 0) { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + vm.expectRevert(expectedError); + _reprovision(amount); + } + + function testReprovision_RevertWhen_StillThawing( + uint64 thawingPeriod, + uint256 provisionAmount + ) + public + useIndexer + useProvision(provisionAmount, 0, thawingPeriod) + useThawRequest(provisionAmount) + { + vm.assume(thawingPeriod > 0); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingStillThawing(uint256,uint256)", + block.timestamp, + block.timestamp + thawingPeriod + ); + vm.expectRevert(expectedError); + _reprovision(provisionAmount); + } + + function testReprovision_RevertWhen_NotEnoughThawedTokens( + uint64 thawingPeriod, + uint256 provisionAmount, + uint256 newProvisionAmount + ) + public + useIndexer + useProvision(provisionAmount, 0, thawingPeriod) + useThawRequest(provisionAmount) + { + newProvisionAmount = bound(newProvisionAmount, provisionAmount + 1, type(uint256).max - provisionAmount); + skip(thawingPeriod + 1); + + _createProvision(newDataService, newProvisionAmount, 0, thawingPeriod); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + vm.expectRevert(expectedError); + _reprovision(newProvisionAmount); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol new file mode 100644 index 000000000..2b3c8c5b1 --- /dev/null +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingSlashTest is HorizonStakingTest { + + modifier useDelegationSlashingDisabled() { + address msgSender; + (, msgSender,) = vm.readCallers(); + vm.startPrank(users.governor); + staking.setDelegationSlashingEnabled(false); + vm.startPrank(msgSender); + _; + } + + function _slash(uint256 amount, uint256 verifierCutAmount) private { + staking.slash(users.indexer, amount, verifierCutAmount, subgraphDataServiceAddress); + } + + function testSlash_Tokens( + uint256 amount, + uint32 maxVerifierCut, + uint256 slashAmount, + uint256 verifierCutAmount + ) public useIndexer useProvision(amount, maxVerifierCut, 0) { + verifierCutAmount = bound(verifierCutAmount, 0, maxVerifierCut); + + // TODO: when slashing for low amounts there's an arithmetic underflow + slashAmount = bound(slashAmount, MIN_PROVISION_SIZE, amount); + + vm.startPrank(subgraphDataServiceAddress); + _slash(slashAmount, verifierCutAmount); + + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, amount - slashAmount); + + uint256 verifierTokens = token.balanceOf(subgraphDataServiceAddress); + assertEq(verifierTokens, verifierCutAmount); + } + + // TODO: Should be re-enabled when slashin is fixed to count for delegated tokens + // function testSlash_DelegationDisabled_SlashingOverProvisionTokens( + // uint256 amount, + // uint256 slashAmount, + // uint256 verifierCutAmount, + // uint256 delegationAmount + // ) public useIndexer useProvision(amount, 100000, 0) useDelegationSlashingDisabled { + // vm.assume(slashAmount > amount); + // vm.assume(delegationAmount > 0); + // uint32 delegationRatio = 5; + + // vm.stopPrank(); + // vm.startPrank(users.delegator); + // _delegate(delegationAmount); + + // vm.startPrank(subgraphDataServiceAddress); + // _slash(slashAmount, verifierCutAmount); + + // uint256 provisionProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + // assertEq(provisionProviderTokens, 0 ether); + + // uint256 verifierTokens = token.balanceOf(address(subgraphDataServiceAddress)); + // assertEq(verifierTokens, verifierCutAmount); + + // uint256 delegatedTokens = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, delegationRatio); + // assertEq(delegatedTokens, delegationAmount); + // } + + function testSlash_RevertWhen_NoProvision( + uint256 amount, + uint256 slashAmount + ) public useIndexer useStake(amount) { + // TODO: when slashing for low amounts there's an arithmetic underflow + slashAmount = bound(slashAmount, MIN_PROVISION_SIZE, amount); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientTokens(uint256,uint256)", + slashAmount, + 0 ether + ); + vm.expectRevert(expectedError); + vm.startPrank(subgraphDataServiceAddress); + _slash(slashAmount, 0); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/stake/stake.t.sol b/packages/horizon/test/staking/stake/stake.t.sol new file mode 100644 index 000000000..bcdec35c9 --- /dev/null +++ b/packages/horizon/test/staking/stake/stake.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingStakeTest is HorizonStakingTest { + + function testStake_Tokens(uint256 amount) public useIndexer useStake(amount) { + assertTrue(staking.getStake(address(users.indexer)) == amount); + } + + function testStake_RevertWhen_ZeroTokens() public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + vm.expectRevert(expectedError); + staking.stake(0); + } + + function testStakeTo_Tokens(uint256 amount) public useOperator useStakeTo(users.indexer, amount) { + assertTrue(staking.getStake(address(users.indexer)) == amount); + } + + function testStakeTo_RevertWhen_ZeroTokens() public useOperator { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + vm.expectRevert(expectedError); + staking.stakeTo(users.indexer, 0); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/stake/unstake.t.sol b/packages/horizon/test/staking/stake/unstake.t.sol new file mode 100644 index 000000000..6285ef9c0 --- /dev/null +++ b/packages/horizon/test/staking/stake/unstake.t.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingUnstakeTest is HorizonStakingTest { + + function testUnstake_Tokens( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) + public + useIndexer + useProvision(amount, maxVerifierCut, thawingPeriod) + useThawAndDeprovision(amount, thawingPeriod) + { + uint256 previousIndexerTokens = token.balanceOf(users.indexer); + staking.unstake(amount); + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, 0 ether); + + uint256 newIndexerBalance = token.balanceOf(users.indexer); + assertEq(newIndexerBalance - previousIndexerTokens, amount); + } + + function testUnstake_RevertWhen_ZeroTokens( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) + public + useIndexer + useProvision(amount, maxVerifierCut, thawingPeriod) + useThawAndDeprovision(amount, thawingPeriod) + { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + vm.expectRevert(expectedError); + staking.unstake(0); + } + + function testUnstake_RevertWhen_NoIdleStake( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) + public + useIndexer + useProvision(amount, maxVerifierCut, thawingPeriod) + { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); + vm.expectRevert(expectedError); + staking.unstake(amount); + } + + function testUnstake_RevertWhen_NotDeprovision( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) + public + useIndexer + useProvision(amount, maxVerifierCut, thawingPeriod) + useThawRequest(amount) + { + skip(thawingPeriod + 1); + + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); + vm.expectRevert(expectedError); + staking.unstake(amount); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol new file mode 100644 index 000000000..e139f219d --- /dev/null +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; + +import { IHorizonStakingTypes } from "../../../contracts/interfaces/IHorizonStakingTypes.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingThawTest is HorizonStakingTest { + + function testThaw_Tokens( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + thawAmount = bound(thawAmount, 1, amount); + bytes32 expectedThawRequestId = keccak256( + abi.encodePacked(users.indexer, subgraphDataServiceAddress, uint256(0)) + ); + bytes32 thawRequestId = _createThawRequest(thawAmount); + assertEq(thawRequestId, expectedThawRequestId); + + ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + assertEq(thawRequest.shares, thawAmount); + assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); + } + + function testThaw_MultipleRequests( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount, + uint256 thawAmount2 + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + thawAmount = bound(thawAmount, 1, amount - 1); + thawAmount2 = bound(thawAmount2, 1, amount - thawAmount); + bytes32 thawRequestId = _createThawRequest(thawAmount); + bytes32 thawRequestId2 = _createThawRequest(thawAmount2); + + ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + assertEq(thawRequest.shares, thawAmount); + assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); + assertEq(thawRequest.next, thawRequestId2); + + ThawRequest memory thawRequest2 = staking.getThawRequest(thawRequestId2); + uint256 totalThawAmount = thawAmount + thawAmount2; + assertEq(thawRequest2.shares, (thawRequest.shares * thawAmount2) / totalThawAmount); + assertEq(thawRequest2.thawingUntil, block.timestamp + thawingPeriod); + } + + function testThaw_OperatorCanStartThawing( + uint256 amount, + uint64 thawingPeriod + ) public useOperator useProvision(amount, 0, thawingPeriod) { + bytes32 thawRequestId = _createThawRequest(amount); + + ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + assertEq(thawRequest.shares, amount); + assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); + } + + function testThaw_RevertWhen_OperatorNotAuthorized( + uint256 amount, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + vm.startPrank(users.operator); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingNotAuthorized(address,address,address)", + users.operator, + users.indexer, + subgraphDataServiceAddress + ); + vm.expectRevert(expectedError); + _createThawRequest(amount); + } + + function testThaw_RevertWhen_InsufficientTokensAvailable( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + vm.assume(thawAmount > amount); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientTokens(uint256,uint256)", + thawAmount, + amount + ); + vm.expectRevert(expectedError); + _createThawRequest(thawAmount); + } + + function testThaw_RevertWhen_OverMaxThawRequests( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + // vm.assume(thawAmount > 0); + // vm.assume(amount / (MAX_THAW_REQUESTS + 1) > thawAmount); + thawAmount = bound(thawAmount, 1, amount / (MAX_THAW_REQUESTS + 1)); + + for (uint256 i = 0; i < 100; i++) { + _createThawRequest(thawAmount); + } + + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingTooManyThawRequests()"); + vm.expectRevert(expectedError); + _createThawRequest(thawAmount); + } + + function testThaw_RevertWhen_ThawingZeroTokens( + uint256 amount, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + uint256 thawAmount = 0 ether; + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + vm.expectRevert(expectedError); + _createThawRequest(thawAmount); + } +} \ No newline at end of file diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index bcf3295d8..00c253bbd 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -9,4 +9,10 @@ abstract contract Constants { uint256 internal constant revokeCollectorThawingPeriod = 60; // GraphPayments parameters uint256 internal constant protocolPaymentCut = 10000; + // Staking constants + uint256 internal constant MAX_THAW_REQUESTS = 100; + uint256 internal constant MIN_PROVISION_SIZE = 1e18; + uint32 internal constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% in parts per million + uint64 internal constant MAX_THAWING_PERIOD = 28 days; + uint256 internal constant MIN_DELEGATION = 1e18; } \ No newline at end of file diff --git a/packages/horizon/test/utils/Users.sol b/packages/horizon/test/utils/Users.sol index e86bf8faf..3329d69da 100644 --- a/packages/horizon/test/utils/Users.sol +++ b/packages/horizon/test/utils/Users.sol @@ -8,4 +8,5 @@ struct Users { address operator; address gateway; address verifier; + address delegator; } \ No newline at end of file From ed3fa1e891034aae837e26f73b6babb1c6e87bdf Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Sat, 25 May 2024 12:34:28 -0300 Subject: [PATCH 074/277] chore: update solidity version --- packages/horizon/test/payments/GraphPayments.t.sol | 6 +----- packages/horizon/test/staking/HorizonStaking.t.sol | 4 ++-- packages/horizon/test/staking/delegation/delegate.t.sol | 2 +- packages/horizon/test/staking/delegation/undelegate.t.sol | 2 +- packages/horizon/test/staking/delegation/withdraw.t.sol | 2 +- packages/horizon/test/staking/operator/operator.t.sol | 2 +- packages/horizon/test/staking/provision/deprovision.t.sol | 2 +- packages/horizon/test/staking/provision/provision.t.sol | 2 +- packages/horizon/test/staking/provision/reprovision.t.sol | 2 +- packages/horizon/test/staking/slash/slash.t.sol | 2 +- packages/horizon/test/staking/stake/stake.t.sol | 2 +- packages/horizon/test/staking/stake/unstake.t.sol | 2 +- packages/horizon/test/staking/thaw/thaw.t.sol | 4 ++-- 13 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 4449bbdcc..70806f42f 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -42,11 +42,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { function testCollect_RevertWhen_InsufficientAmount( uint256 amount, uint256 tokensDataService -<<<<<<< HEAD - ) public useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { -======= - ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(0, delegationFeeCut) { ->>>>>>> 9fa803b7 (chore: staking tests refactor) + ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { vm.assume(tokensDataService <= 10_000_000_000 ether); vm.assume(tokensDataService > amount); diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index 431ce0296..b2c256a2d 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { IHorizonStakingTypes } from "../../contracts/interfaces/IHorizonStakingTypes.sol"; +import { IHorizonStakingTypes } from "../../contracts/interfaces/internal/IHorizonStakingTypes.sol"; import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 279c2f7f7..603020ef7 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 73c7a913e..7d31112ff 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 593a2dae5..255124cb9 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/operator/operator.t.sol b/packages/horizon/test/staking/operator/operator.t.sol index 6fffe0cf3..f9f6e1692 100644 --- a/packages/horizon/test/staking/operator/operator.t.sol +++ b/packages/horizon/test/staking/operator/operator.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index 3afb3a7b1..afaa11a5b 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index ee9591205..3d9974a9e 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 2c10e9060..4198eaea4 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 2b3c8c5b1..2306e93f7 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/stake/stake.t.sol b/packages/horizon/test/staking/stake/stake.t.sol index bcdec35c9..048d6b4a7 100644 --- a/packages/horizon/test/staking/stake/stake.t.sol +++ b/packages/horizon/test/staking/stake/stake.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/stake/unstake.t.sol b/packages/horizon/test/staking/stake/unstake.t.sol index 6285ef9c0..8acd695fe 100644 --- a/packages/horizon/test/staking/stake/unstake.t.sol +++ b/packages/horizon/test/staking/stake/unstake.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index e139f219d..22fbb9fe1 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { IHorizonStakingTypes } from "../../../contracts/interfaces/IHorizonStakingTypes.sol"; +import { IHorizonStakingTypes } from "../../../contracts/interfaces/internal/IHorizonStakingTypes.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingThawTest is HorizonStakingTest { From b05d0649cf80d0d5efef729105b54ca25e00bfeb Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Mon, 27 May 2024 11:04:48 -0300 Subject: [PATCH 075/277] fix: failing tests --- .../contracts/staking/HorizonStaking.sol | 2 +- .../horizon/test/escrow/GraphEscrow.t.sol | 4 +--- packages/horizon/test/escrow/collect.t.sol | 14 ++++++++----- packages/horizon/test/escrow/collector.t.sol | 8 ++++---- packages/horizon/test/escrow/thaw.t.sol | 4 ++-- packages/horizon/test/escrow/withdraw.t.sol | 6 ++---- .../test/staking/delegation/undelegate.t.sol | 16 +++++++++------ .../test/staking/delegation/withdraw.t.sol | 2 +- .../test/staking/provision/deprovision.t.sol | 7 +++---- .../test/staking/provision/provision.t.sol | 20 +++++++++++++++---- .../test/staking/provision/reprovision.t.sol | 7 +++---- .../horizon/test/staking/slash/slash.t.sol | 4 ++-- packages/horizon/test/staking/thaw/thaw.t.sol | 6 +++--- 13 files changed, 57 insertions(+), 43 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 95174f626..9880a352f 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -525,7 +525,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } function setMaxThawingPeriod(uint64 maxThawingPeriod) external override onlyGovernor { - maxThawingPeriod = _maxThawingPeriod; + _maxThawingPeriod = maxThawingPeriod; emit MaxThawingPeriodSet(_maxThawingPeriod); } diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index 70c96466f..5d0e01954 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -14,13 +14,11 @@ contract GraphEscrowTest is HorizonStakingSharedTest { } modifier approveEscrow(uint256 tokens) { - changePrank(users.gateway); _approveEscrow(tokens); _; } modifier useDeposit(uint256 tokens) { - changePrank(users.gateway); vm.assume(tokens > 0); vm.assume(tokens <= 10_000_000_000 ether); _depositTokens(tokens); @@ -28,7 +26,7 @@ contract GraphEscrowTest is HorizonStakingSharedTest { } modifier useCollector(uint256 tokens) { - changePrank(users.gateway); + vm.assume(tokens > 0); escrow.approveCollector(users.verifier, tokens); _; } diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 04d71252d..5a9a71fa1 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -33,7 +33,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { function testCollect_RevertWhen_CollectorNotAuthorized(uint256 amount) public { vm.startPrank(users.verifier); uint256 dataServiceCut = 30000; // 3% - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); vm.expectRevert(expectedError); escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, dataServiceCut); vm.stopPrank(); @@ -45,8 +45,12 @@ contract GraphEscrowCollectTest is GraphEscrowTest { ) public useGateway useCollector(insufficientAmount) useDeposit(amount) { vm.assume(insufficientAmount < amount); - changePrank(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAllowance(uint256,uint256)", insufficientAmount, amount); + vm.startPrank(users.verifier); + bytes memory expectedError = abi.encodeWithSignature( + "PaymentsEscrowInsufficientAllowance(uint256,uint256)", + insufficientAmount, + amount + ); vm.expectRevert(expectedError); escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); } @@ -57,8 +61,8 @@ contract GraphEscrowCollectTest is GraphEscrowTest { ) public useGateway useCollector(amount) useDeposit(insufficientAmount) { vm.assume(insufficientAmount < amount); - changePrank(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientBalance(uint256,uint256)", insufficientAmount, amount); + vm.startPrank(users.verifier); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInsufficientBalance(uint256,uint256)", insufficientAmount, amount); vm.expectRevert(expectedError); escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); vm.stopPrank(); diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index f90eff6dc..83d7fb42a 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -20,7 +20,7 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { uint256 smallerAmount ) public useGateway useCollector(amount) { vm.assume(smallerAmount < amount); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientAllowance(uint256,uint256)", amount, smallerAmount); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInconsistentAllowance(uint256,uint256)", amount, smallerAmount); vm.expectRevert(expectedError); escrow.approveCollector(users.verifier, smallerAmount); } @@ -52,7 +52,7 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { } function testCollector_RevertWhen_CancelThawIsNotThawing(uint256 amount) public useGateway useCollector(amount) { - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowNotThawing()"); vm.expectRevert(expectedError); escrow.cancelThawCollector(users.verifier); vm.stopPrank(); @@ -70,14 +70,14 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { } function testCollector_RevertWhen_RevokeIsNotThawing(uint256 amount) public useGateway useCollector(amount) { - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowNotThawing()"); vm.expectRevert(expectedError); escrow.revokeCollector(users.verifier); } function testCollector_RevertWhen_RevokeIsStillThawing(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + revokeCollectorThawingPeriod); vm.expectRevert(expectedError); escrow.revokeCollector(users.verifier); } diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index bf689486c..110d262e3 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -18,7 +18,7 @@ contract GraphEscrowThawTest is GraphEscrowTest { function testThaw_RevertWhen_InsufficientThawAmount( uint256 amount ) public useGateway useDeposit(amount) { - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientTokensThawing()"); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInsufficientTokensThawing()"); vm.expectRevert(expectedError); escrow.thaw(users.indexer, 0); } @@ -27,7 +27,7 @@ contract GraphEscrowThawTest is GraphEscrowTest { uint256 amount ) public useGateway useDeposit(amount) { uint256 overAmount = amount + 1; - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowInsufficientBalance(uint256,uint256)", amount, overAmount); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInsufficientBalance(uint256,uint256)", amount, overAmount); vm.expectRevert(expectedError); escrow.thaw(users.indexer, overAmount); } diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index 15d1d94ed..a541c818b 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -30,19 +30,17 @@ contract GraphEscrowWithdrawTest is GraphEscrowTest { } function testWithdraw_RevertWhen_NotThawing(uint256 amount) public useGateway useDeposit(amount) { - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowNotThawing()"); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowNotThawing()"); vm.expectRevert(expectedError); escrow.withdraw(users.indexer); - vm.stopPrank(); } function testWithdraw_RevertWhen_StillThawing( uint256 amount, uint256 thawAmount ) public useGateway depositAndThawTokens(amount, thawAmount) { - bytes memory expectedError = abi.encodeWithSignature("GraphEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + withdrawEscrowThawingPeriod); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + withdrawEscrowThawingPeriod); vm.expectRevert(expectedError); escrow.withdraw(users.indexer); - vm.stopPrank(); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 7d31112ff..e3b355c30 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -30,7 +30,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { // TODO: maybe create a changePrank vm.stopPrank(); vm.startPrank(users.delegator); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroShares()"); vm.expectRevert(expectedError); _undelegate(0); } @@ -47,9 +47,9 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { vm.assume(overDelegationShares > delegation.shares); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokens(uint256,uint256)", - overDelegationShares, - delegation.shares + "HorizonStakingInvalidSharesAmount(uint256,uint256)", + delegation.shares, + overDelegationShares ); vm.expectRevert(expectedError); _undelegate(overDelegationShares); @@ -69,8 +69,12 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { vm.startPrank(users.delegator); uint256 minShares = delegationAmount - MIN_DELEGATION + 1; withdrawShares = bound(withdrawShares, minShares, delegationAmount - 1); - - vm.expectRevert("!minimum-delegation"); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientTokens(uint256,uint256)", + delegationAmount - withdrawShares, + MIN_DELEGATION + ); + vm.expectRevert(expectedError); _undelegate(withdrawShares); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 255124cb9..2db1a4237 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -65,7 +65,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); _withdrawDelegated(); } diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index afaa11a5b..ba8584d17 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -62,7 +62,7 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { uint32 maxVerifierCut, uint64 thawingPeriod ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); vm.expectRevert(expectedError); _deprovision(amount); } @@ -74,8 +74,7 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { vm.assume(thawingPeriod > 0); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingStillThawing(uint256,uint256)", - block.timestamp, + "HorizonStakingStillThawing(uint256)", block.timestamp + thawingPeriod ); vm.expectRevert(expectedError); @@ -91,7 +90,7 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { vm.assume(deprovisionAmount > amount); skip(thawingPeriod + 1); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); vm.expectRevert(expectedError); _deprovision(deprovisionAmount); } diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index 3d9974a9e..f92f85be1 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -17,8 +17,12 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { } function testProvision_RevertWhen_InsufficientTokens(uint256 amount) public useIndexer useStake(1000 ether) { - vm.assume(amount < MIN_PROVISION_SIZE); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientTokens(uint256,uint256)", MIN_PROVISION_SIZE, amount); + amount = bound(amount, 0, MIN_PROVISION_SIZE - 1); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInvalidTokens(uint256,uint256)", + amount, + MIN_PROVISION_SIZE + ); vm.expectRevert(expectedError); staking.provision(users.indexer, subgraphDataServiceAddress, amount, 0, 0); } @@ -29,7 +33,11 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { ) public useIndexer useStake(amount) { vm.assume(amount > MIN_PROVISION_SIZE); vm.assume(maxVerifierCut > MAX_MAX_VERIFIER_CUT); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingMaxVerifierCutExceeded(uint32,uint32)", MAX_MAX_VERIFIER_CUT, maxVerifierCut); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInvalidMaxVerifierCut(uint32,uint32)", + maxVerifierCut, + MAX_MAX_VERIFIER_CUT + ); vm.expectRevert(expectedError); staking.provision(users.indexer, subgraphDataServiceAddress, amount, maxVerifierCut, 0); } @@ -40,7 +48,11 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { ) public useIndexer useStake(amount) { vm.assume(amount > MIN_PROVISION_SIZE); vm.assume(thawingPeriod > MAX_THAWING_PERIOD); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingMaxThawingPeriodExceeded(uint64,uint64)", MAX_THAWING_PERIOD, thawingPeriod); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInvalidThawingPeriod(uint64,uint64)", + thawingPeriod, + MAX_THAWING_PERIOD + ); vm.expectRevert(expectedError); staking.provision(users.indexer, subgraphDataServiceAddress, amount, 0, thawingPeriod); } diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 4198eaea4..8a7d17d6a 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -86,7 +86,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { function testReprovision_RevertWhen_NoThawingTokens( uint256 amount ) public useIndexer useProvision(amount, 0, 0) { - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); vm.expectRevert(expectedError); _reprovision(amount); } @@ -102,8 +102,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { { vm.assume(thawingPeriod > 0); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingStillThawing(uint256,uint256)", - block.timestamp, + "HorizonStakingStillThawing(uint256)", block.timestamp + thawingPeriod ); vm.expectRevert(expectedError); @@ -124,7 +123,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { skip(thawingPeriod + 1); _createProvision(newDataService, newProvisionAmount, 0, thawingPeriod); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNotEnoughThawedTokens()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); vm.expectRevert(expectedError); _reprovision(newProvisionAmount); } diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 2306e93f7..9a0951f23 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -77,8 +77,8 @@ contract HorizonStakingSlashTest is HorizonStakingTest { slashAmount = bound(slashAmount, MIN_PROVISION_SIZE, amount); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientTokens(uint256,uint256)", - slashAmount, - 0 ether + 0 ether, + slashAmount ); vm.expectRevert(expectedError); vm.startPrank(subgraphDataServiceAddress); diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index 22fbb9fe1..3d2ce4b90 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -80,9 +80,9 @@ contract HorizonStakingThawTest is HorizonStakingTest { ) public useIndexer useProvision(amount, 0, thawingPeriod) { vm.assume(thawAmount > amount); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokens(uint256,uint256)", - thawAmount, - amount + "HorizonStakingInsufficientTokensAvailable(uint256,uint256)", + amount, + thawAmount ); vm.expectRevert(expectedError); _createThawRequest(thawAmount); From 5655a898512741d4c05c5da3ff37aa464dca0d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 27 May 2024 12:44:51 -0300 Subject: [PATCH 076/277] chore: disable optimizer for tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/foundry.toml | 9 ++++++++- packages/horizon/package.json | 2 +- packages/subgraph-service/foundry.toml | 9 ++++++++- packages/subgraph-service/package.json | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/horizon/foundry.toml b/packages/horizon/foundry.toml index c9e7f0534..a1826d45c 100644 --- a/packages/horizon/foundry.toml +++ b/packages/horizon/foundry.toml @@ -7,4 +7,11 @@ cache_path = 'cache_forge' fs_permissions = [{ access = "read", path = "./"}] optimizer = true optimizer-runs = 200 -via_ir = true \ No newline at end of file +via_ir = true + +[profile.lite] +optimizer = false +optimizer-runs = 1 + +[profile.lite.optimizer_details.yulDetails] +optimizerSteps = ':' \ No newline at end of file diff --git a/packages/horizon/package.json b/packages/horizon/package.json index 00c266f49..2eee03723 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -9,7 +9,7 @@ "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", - "build": "forge build && hardhat compile", + "build": "FOUNDRY_PROFILE=lite forge build && hardhat compile", "test": "forge test -vvv && hardhat test" }, "devDependencies": { diff --git a/packages/subgraph-service/foundry.toml b/packages/subgraph-service/foundry.toml index 4c96e433b..d4c30311f 100644 --- a/packages/subgraph-service/foundry.toml +++ b/packages/subgraph-service/foundry.toml @@ -6,4 +6,11 @@ test = 'test' cache_path = 'cache_forge' optimizer = true optimizer-runs = 200 -via_ir = true \ No newline at end of file +via_ir = true + +[profile.lite] +optimizer = false +optimizer-runs = 1 + +[profile.lite.optimizer_details.yulDetails] +optimizerSteps = ':' \ No newline at end of file diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index 8df36e35f..1cfe655b2 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -9,7 +9,7 @@ "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", - "build": "forge build && hardhat compile", + "build": "FOUNDRY_PROFILE=lite forge build && hardhat compile", "test": "forge test -vvv && hardhat test" }, "devDependencies": { From 6a48e4da5f5a42e5d1c75d84e520c5e106de5aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 27 May 2024 13:36:44 -0300 Subject: [PATCH 077/277] fix: foundry profile usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/package.json | 4 ++-- packages/subgraph-service/package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/horizon/package.json b/packages/horizon/package.json index 2eee03723..1118b1b19 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -9,8 +9,8 @@ "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", - "build": "FOUNDRY_PROFILE=lite forge build && hardhat compile", - "test": "forge test -vvv && hardhat test" + "build": "forge build && hardhat compile", + "test": "FOUNDRY_PROFILE=lite forge test -vvv && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index 1cfe655b2..6e963c603 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -9,8 +9,8 @@ "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", - "build": "FOUNDRY_PROFILE=lite forge build && hardhat compile", - "test": "forge test -vvv && hardhat test" + "build": "forge build && hardhat compile", + "test": "FOUNDRY_PROFILE=lite forge test -vvv && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", From 6e3ab78b021e3a566d6c5def8def8a9132735925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 27 May 2024 14:29:03 -0300 Subject: [PATCH 078/277] chore: remove duplicate code from staking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/staking/HorizonStaking.sol | 38 +------------------ 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 9880a352f..0c5af9853 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -335,43 +335,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address newServiceProvider, uint256 minSharesForNewProvider ) external override notPaused { - DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); - Delegation storage delegation = pool.delegators[msg.sender]; - uint256 thawedTokens = 0; - - uint256 sharesThawing = pool.sharesThawing; - uint256 tokensThawing = pool.tokensThawing; - require(delegation.nThawRequests > 0, HorizonStakingNothingThawing()); - bytes32 thawRequestId = delegation.firstThawRequestId; - while (thawRequestId != bytes32(0)) { - ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - if (thawRequest.thawingUntil <= block.timestamp) { - uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; - tokensThawing = tokensThawing - tokens; - sharesThawing = sharesThawing - thawRequest.shares; - thawedTokens = thawedTokens + tokens; - delete _thawRequests[thawRequestId]; - delegation.firstThawRequestId = thawRequest.next; - delegation.nThawRequests -= 1; - if (delegation.nThawRequests == 0) { - delegation.lastThawRequestId = bytes32(0); - } - } else { - break; - } - thawRequestId = thawRequest.next; - } - - pool.tokens = pool.tokens - thawedTokens; - pool.sharesThawing = sharesThawing; - pool.tokensThawing = tokensThawing; - - if (newServiceProvider != address(0)) { - _delegate(newServiceProvider, verifier, thawedTokens, minSharesForNewProvider); - } else { - _graphToken().pushTokens(msg.sender, thawedTokens); - } - emit DelegatedTokensWithdrawn(serviceProvider, verifier, msg.sender, thawedTokens); + _withdrawDelegated(serviceProvider, verifier, newServiceProvider, minSharesForNewProvider); } function setDelegationFeeCut( From a9277b479e8726b37014d104913b1853187befb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 28 May 2024 11:17:51 -0300 Subject: [PATCH 079/277] feat: add linked list library (#975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServiceFees.sol | 89 ++++--- .../extensions/DataServiceFeesStorage.sol | 10 +- .../interfaces/IDataServiceFees.sol | 15 +- .../internal/IHorizonStakingBase.sol | 20 ++ .../internal/IHorizonStakingMain.sol | 38 +-- .../internal/IHorizonStakingTypes.sol | 11 - .../contracts/libraries/LinkedList.sol | 72 +++++ .../contracts/staking/HorizonStaking.sol | 250 +++++++----------- .../contracts/staking/HorizonStakingBase.sol | 97 ++++++- .../staking/HorizonStakingStorage.sol | 5 + packages/horizon/hardhat.config.ts | 2 +- 11 files changed, 367 insertions(+), 242 deletions(-) create mode 100644 packages/horizon/contracts/libraries/LinkedList.sol diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index cf8787674..b416bcf69 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -5,46 +5,19 @@ import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; import { ProvisionTracker } from "../libraries/ProvisionTracker.sol"; +import { LinkedList } from "../../libraries/LinkedList.sol"; import { DataService } from "../DataService.sol"; import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol"; abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDataServiceFees { using ProvisionTracker for mapping(address => uint256); + using LinkedList for LinkedList.List; function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external virtual { _releaseStake(feeType, msg.sender, n); } - /// @notice Release expired stake claims for a service provider - /// @param _n The number of stake claims to release, or 0 to release all - function _releaseStake(IGraphPayments.PaymentTypes _feeType, address _serviceProvider, uint256 _n) internal { - bool releaseAll = _n == 0; - - // check the stake claims list - // TODO: evaluate replacing with OZ DoubleEndedQueue - bytes32 head = claimsLists[_feeType][_serviceProvider].head; - while (head != bytes32(0) && (releaseAll || _n > 0)) { - StakeClaim memory claim = _getStakeClaim(head); - - if (block.timestamp >= claim.releaseAt) { - // Release stake - feesProvisionTracker[_feeType].release(_serviceProvider, claim.tokens); - - // Update list and refresh pointer - StakeClaimsList storage claimsList = claimsLists[_feeType][_serviceProvider]; - claimsList.head = claim.nextClaim; - delete claims[head]; - head = claimsList.head; - if (!releaseAll) _n--; - - emit StakeClaimReleased(_serviceProvider, claimsList.head, claim.tokens, claim.releaseAt); - } else { - break; - } - } - } - function _lockStake( IGraphPayments.PaymentTypes _feeType, address _serviceProvider, @@ -53,7 +26,9 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat ) internal { feesProvisionTracker[_feeType].lock(_graphStaking(), _serviceProvider, _tokens, maximumDelegationRatio); - StakeClaimsList storage claimsList = claimsLists[_feeType][_serviceProvider]; + LinkedList.List storage claimsList = claimsLists[_feeType][_serviceProvider]; + + // Save item and add to list bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); claims[claimId] = StakeClaim({ serviceProvider: _serviceProvider, @@ -62,12 +37,52 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat releaseAt: _unlockTimestamp, nextClaim: bytes32(0) }); + if (claimsList.count != 0) claims[claimsList.tail].nextClaim = claimId; + claimsList.add(claimId); + + emit StakeClaimLocked(_serviceProvider, _feeType, claimId, _tokens, _unlockTimestamp); + } + + /// @notice Release expired stake claims for a service provider + /// @param _n The number of stake claims to release, or 0 to release all + function _releaseStake(IGraphPayments.PaymentTypes _feeType, address _serviceProvider, uint256 _n) internal { + LinkedList.List storage claimsList = claimsLists[_feeType][_serviceProvider]; + (uint256 claimsReleased, bytes memory data) = claimsList.traverse( + _getNextStakeClaim, + _processStakeClaim, + _deleteStakeClaim, + abi.encode(0), + _n + ); + + emit StakeClaimsReleased(_serviceProvider, _feeType, claimsReleased, abi.decode(data, (uint256))); + } + + function _processStakeClaim(bytes32 _claimId, bytes memory acc) private returns (bool, bool, bytes memory) { + StakeClaim memory claim = _getStakeClaim(_claimId); + + // early exit + if (claim.releaseAt > block.timestamp) { + return (true, false, LinkedList.NULL_BYTES); + } + + // decode + (IGraphPayments.PaymentTypes _feeType, address _serviceProvider) = abi.decode( + acc, + (IGraphPayments.PaymentTypes, address) + ); - claims[claimsList.tail].nextClaim = claimId; - claimsList.tail = claimId; - claimsList.nonce += 1; + // process + feesProvisionTracker[_feeType].release(_serviceProvider, claim.tokens); + emit StakeClaimReleased(_serviceProvider, _feeType, _claimId, claim.tokens, claim.releaseAt); - emit StakeClaimLocked(_serviceProvider, claimId, _tokens, _unlockTimestamp); + // encode + acc = abi.encode(abi.decode(acc, (uint256)) + claim.tokens); + return (false, true, acc); + } + + function _deleteStakeClaim(bytes32 _claimId) private { + delete claims[_claimId]; } function _getStakeClaim(bytes32 _claimId) private view returns (StakeClaim memory) { @@ -76,6 +91,12 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat return claim; } + function _getNextStakeClaim(bytes32 _claimId) private view returns (bytes32) { + StakeClaim memory claim = claims[_claimId]; + require(claim.createdAt != 0, DataServiceFeesClaimNotFound(_claimId)); + return claim.nextClaim; + } + function _buildStakeClaimId(address _serviceProvider, uint256 _nonce) private view returns (bytes32) { return keccak256(abi.encodePacked(address(this), _serviceProvider, _nonce)); } diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 814d246a7..7e867c35e 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -4,15 +4,17 @@ pragma solidity 0.8.26; import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; -abstract contract DataServiceFeesV1Storage { - /// @notice List of all locked stake claims to be released to service providers - mapping(bytes32 claimId => IDataServiceFees.StakeClaim claim) public claims; +import { LinkedList } from "../../libraries/LinkedList.sol"; +abstract contract DataServiceFeesV1Storage { mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => uint256 tokens)) public feesProvisionTracker; + /// @notice List of all locked stake claims to be released to service providers + mapping(bytes32 claimId => IDataServiceFees.StakeClaim claim) public claims; + /// @notice Service providers registered in the data service - mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => IDataServiceFees.StakeClaimsList list)) + mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => LinkedList.List list)) public claimsLists; /// @dev Gap to allow adding variables in future upgrades diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index bbbab0d8b..9e39e62fd 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -5,12 +5,6 @@ import { IDataService } from "./IDataService.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; interface IDataServiceFees is IDataService { - struct StakeClaimsList { - bytes32 head; - bytes32 tail; - uint256 nonce; - } - /// A locked stake claim to be released to a service provider struct StakeClaim { address serviceProvider; @@ -25,16 +19,25 @@ interface IDataServiceFees is IDataService { event StakeClaimLocked( address indexed serviceProvider, + IGraphPayments.PaymentTypes indexed feeType, bytes32 indexed claimId, uint256 tokens, uint256 unlockTimestamp ); event StakeClaimReleased( address indexed serviceProvider, + IGraphPayments.PaymentTypes indexed feeType, bytes32 indexed claimId, uint256 tokens, uint256 releaseAt ); + event StakeClaimsReleased( + address indexed serviceProvider, + IGraphPayments.PaymentTypes indexed feeType, + uint256 claimsCount, + uint256 tokensReleased + ); + error DataServiceFeesClaimNotFound(bytes32 claimId); function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index 0d367547f..76ad132aa 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -21,6 +21,26 @@ interface IHorizonStakingBase { */ event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); + event ThawRequestCreated( + address indexed serviceProvider, + address indexed verifier, + address indexed owner, + uint256 shares, + uint64 thawingUntil, + bytes32 thawRequestId + ); + event ThawRequestFulfilled(bytes32 indexed thawRequestId, uint256 tokens, uint256 shares, uint64 thawingUntil); + event ThawRequestsFulfilled( + address indexed serviceProvider, + address indexed verifier, + address indexed owner, + uint256 thawRequestsFulfilled, + uint256 tokens + ); + + error HorizonStakingNothingThawing(); + error HorizonStakingTooManyThawRequests(); + function getStake(address serviceProvider) external view returns (uint256); function getDelegatedTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 27f63b3c8..ced1957b9 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -32,26 +32,9 @@ interface IHorizonStakingMain is IHorizonStakingBase { */ event ProvisionIncreased(address indexed serviceProvider, address indexed verifier, uint256 tokens); - /** - * @dev Emitted when a thawing request is initiated by a service provider - */ - event ProvisionThawInitiated( - address indexed serviceProvider, - address indexed verifier, - uint256 tokens, - uint64 thawingUntil, - bytes32 indexed thawRequestId - ); + event ProvisionThawed(address indexed serviceProvider, address indexed verifier, uint256 tokens); - /** - * @dev Emitted when a service provider removes tokens from a provision after thawing - */ - event ProvisionThawFulfilled( - address indexed serviceProvider, - address indexed verifier, - uint256 tokens, - bytes32 indexed thawRequestId - ); + event TokensDeprovisioned(address indexed serviceProvider, address indexed verifier, uint256 tokens); event ProvisionSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); @@ -131,11 +114,9 @@ interface IHorizonStakingMain is IHorizonStakingBase { error HorizonStakingInsufficientCapacity(); error HorizonStakingInsufficientCapacityForLegacyAllocations(); error HorizonStakingInsufficientTokensAvailable(uint256 tokensAvailable, uint256 tokensRequired); - error HorizonStakingTooManyThawRequests(); error HorizonStakingInsufficientTokens(uint256 available, uint256 tokensRequired); error HorizonStakingSlippageProtection(uint256 minExpectedShares, uint256 actualShares); error HorizonStakingVerifierNotAllowed(address verifier); - error HorizonStakingNothingThawing(); error HorizonStakingVerifierTokensTooHigh(uint256 tokensVerifier, uint256 maxVerifierTokens); error HorizonStakingNotEnoughDelegation(uint256 tokensAvailable, uint256 tokensRequired); error HorizonStakingStillThawing(uint256 until); @@ -182,16 +163,22 @@ interface IHorizonStakingMain is IHorizonStakingBase { ) external; // initiate a thawing to remove tokens from a provision - function thaw(address serviceProvider, address verifier, uint256 tokens) external returns (bytes32); + function thaw(address serviceProvider, address verifier, uint256 tokens) external; // add more tokens from idle stake to an existing provision function addToProvision(address serviceProvider, address verifier, uint256 tokens) external; // moves thawed stake from a provision back into the provider's available stake - function deprovision(address serviceProvider, address verifier, uint256 tokens) external; + function deprovision(address serviceProvider, address verifier, uint256 nThawRequests) external; // moves thawed stake from one provision into another provision - function reprovision(address serviceProvider, address oldVerifier, address newVerifier, uint256 tokens) external; + function reprovision( + address serviceProvider, + address oldVerifier, + address newVerifier, + uint256 nThawRequests, + uint256 tokens + ) external; // moves thawed stake back to the owner's account - stake is removed from the protocol function unstake(uint256 tokens) external; @@ -207,7 +194,8 @@ interface IHorizonStakingMain is IHorizonStakingBase { address serviceProvider, address verifier, address newServiceProvider, - uint256 minSharesForNewProvider + uint256 minSharesForNewProvider, + uint256 nThawRequests ) external; function slash( diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index d320dd643..13c64d37d 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -18,9 +18,6 @@ interface IHorizonStakingTypes { // time, in seconds, tokens must thaw before being withdrawn uint64 thawingPeriod; uint64 createdAt; - bytes32 firstThawRequestId; - bytes32 lastThawRequestId; - uint256 nThawRequests; // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed uint32 maxVerifierCutPending; // time, in seconds, tokens must thaw before being withdrawn @@ -32,8 +29,6 @@ interface IHorizonStakingTypes { uint256 tokensStaked; // tokens used in a provision uint256 tokensProvisioned; - // Next nonce to be used to generate thaw request IDs - uint256 nextThawRequestNonce; } struct DelegationPoolInternal { @@ -59,10 +54,6 @@ interface IHorizonStakingTypes { uint256 shares; // Shares owned by a delegator in the pool uint256 __DEPRECATED_tokensLocked; // Tokens locked for undelegation uint256 __DEPRECATED_tokensLockedUntil; // Epoch when locked tokens can be withdrawn - bytes32 firstThawRequestId; - bytes32 lastThawRequestId; - uint256 nThawRequests; - uint256 nextThawRequestNonce; } struct ThawRequest { @@ -86,7 +77,5 @@ interface IHorizonStakingTypes { uint256 __DEPRECATED_tokensLockedUntil; // tokens used in a provision uint256 tokensProvisioned; - // Next nonce to be used to generate thaw request IDs - uint256 nextThawRequestNonce; } } diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol new file mode 100644 index 000000000..28ced852a --- /dev/null +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.26; + +library LinkedList { + using LinkedList for List; + + error LinkedListEmptyList(); + + bytes internal constant NULL_BYTES = bytes(""); + struct List { + bytes32 head; + bytes32 tail; + uint256 nonce; + uint256 count; + } + + function add(List storage self, bytes32 id) internal { + self.tail = id; + self.nonce += 1; + if (self.count == 0) self.head = id; + self.count += 1; + } + + function remove( + List storage self, + function(bytes32) view returns (bytes32) getNextItem, + function(bytes32) deleteItem + ) internal returns (bytes32) { + require(self.count > 0, LinkedListEmptyList()); + bytes32 nextItem = getNextItem(self.head); + deleteItem(self.head); + self.count -= 1; + self.head = nextItem; + if (self.count == 0) self.tail = bytes32(0); + return self.head; + } + + function traverse( + List storage self, + function(bytes32) view returns (bytes32) getNextItem, + function(bytes32, bytes memory) returns (bool, bool, bytes memory) processItem, + function(bytes32) deleteItem, + bytes memory processInitAcc, + uint256 iterations + ) internal returns (uint256, bytes memory) { + uint256 itemCount = 0; + bool traverseAll = iterations == 0; + bytes memory acc = processInitAcc; + + bytes32 cursor = self.head; + + while (cursor != bytes32(0) && (traverseAll || iterations > 0)) { + (bool shouldBreak, bool shouldDelete, bytes memory acc_) = processItem(cursor, acc); + + if (shouldBreak) break; + + acc = acc_; + + if (shouldDelete) { + cursor = self.remove(getNextItem, deleteItem); + } else { + cursor = getNextItem(cursor); + } + + if (!traverseAll) iterations--; + itemCount++; + } + + return (itemCount, acc); + } +} diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 0c5af9853..2986f7c30 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -9,6 +9,7 @@ import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; +import { LinkedList } from "../libraries/LinkedList.sol"; import { HorizonStakingBase } from "./HorizonStakingBase.sol"; @@ -23,6 +24,7 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { using TokenUtils for IGraphToken; using PPMMath for uint256; + using LinkedList for LinkedList.List; /// @dev Maximum value that can be set as the maxVerifierCut in a provision. /// It is equivalent to 100% in parts-per-million @@ -31,9 +33,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /// @dev Minimum size of a provision uint256 private constant MIN_PROVISION_SIZE = 1e18; - /// @dev Maximum number of simultaneous stake thaw requests (per provision) or undelegations (per delegation) - uint256 private constant MAX_THAW_REQUESTS = 100; - /// @dev Fixed point precision uint256 private constant FIXED_POINT_PRECISION = 1e18; @@ -200,49 +199,17 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address verifier, uint256 tokens - ) external override notPaused onlyAuthorized(serviceProvider, verifier) returns (bytes32) { - require(tokens != 0, HorizonStakingInvalidZeroTokens()); - - Provision storage prov = _provisions[serviceProvider][verifier]; - ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; - bytes32 thawRequestId = keccak256(abi.encodePacked(serviceProvider, verifier, sp.nextThawRequestNonce)); - sp.nextThawRequestNonce += 1; - ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - - uint256 tokensAvailable = _getProviderTokensAvailable(serviceProvider, verifier); - require(tokensAvailable >= tokens, HorizonStakingInsufficientTokensAvailable(tokensAvailable, tokens)); - prov.tokensThawing = prov.tokensThawing + tokens; - - if (prov.sharesThawing == 0) { - thawRequest.shares = tokens; - } else { - thawRequest.shares = (prov.sharesThawing * tokens) / prov.tokensThawing; - } - - thawRequest.thawingUntil = uint64(block.timestamp + uint256(prov.thawingPeriod)); - prov.sharesThawing = prov.sharesThawing + thawRequest.shares; - - require(prov.nThawRequests < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); - if (prov.nThawRequests == 0) { - prov.firstThawRequestId = thawRequestId; - } else { - _thawRequests[prov.lastThawRequestId].next = thawRequestId; - } - prov.lastThawRequestId = thawRequestId; - prov.nThawRequests += 1; - - emit ProvisionThawInitiated(serviceProvider, verifier, tokens, thawRequest.thawingUntil, thawRequestId); - - return thawRequestId; + ) external override notPaused onlyAuthorized(serviceProvider, verifier) { + _thaw(serviceProvider, verifier, tokens); } // moves thawed stake from a provision back into the provider's available stake function deprovision( address serviceProvider, address verifier, - uint256 tokens + uint256 nThawRequests ) external override onlyAuthorized(serviceProvider, verifier) notPaused { - _fulfillThawRequests(serviceProvider, verifier, tokens); + _deprovision(serviceProvider, verifier, nThawRequests); } /** @@ -259,6 +226,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address oldVerifier, address newVerifier, + uint256 nThawRequests, uint256 tokens ) external @@ -267,7 +235,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { onlyAuthorized(serviceProvider, oldVerifier) onlyAuthorized(serviceProvider, newVerifier) { - _fulfillThawRequests(serviceProvider, oldVerifier, tokens); + _deprovision(serviceProvider, oldVerifier, nThawRequests); _addToProvision(serviceProvider, newVerifier, tokens); } @@ -333,9 +301,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address verifier, address newServiceProvider, - uint256 minSharesForNewProvider + uint256 minSharesForNewProvider, + uint256 nThawRequests ) external override notPaused { - _withdrawDelegated(serviceProvider, verifier, newServiceProvider, minSharesForNewProvider); + _withdrawDelegated(serviceProvider, verifier, newServiceProvider, minSharesForNewProvider, nThawRequests); } function setDelegationFeeCut( @@ -362,7 +331,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // For backwards compatibility, withdraws delegated tokens from the subgraph data service function withdrawDelegated(address serviceProvider, address newServiceProvider) external notPaused { - _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0); + _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0, 0); } /* @@ -582,6 +551,32 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } } + /** + * @dev Withdraw service provider tokens once the thawing period has passed. + * @param _serviceProvider Address of service provider to withdraw funds from + */ + function _withdraw(address _serviceProvider) private { + // Get tokens available for withdraw and update balance + ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; + uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; + require(tokensToWithdraw > 0, HorizonStakingInvalidZeroTokens()); + require( + block.timestamp >= sp.__DEPRECATED_tokensLockedUntil, + HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) + ); + + // Reset locked tokens + sp.__DEPRECATED_tokensLocked = 0; + sp.__DEPRECATED_tokensLockedUntil = 0; + + sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; + + // Return tokens to the service provider + _graphToken().pushTokens(_serviceProvider, tokensToWithdraw); + + emit StakeWithdrawn(_serviceProvider, tokensToWithdraw); + } + /** * @dev Creates a provision */ @@ -610,9 +605,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { maxVerifierCut: _maxVerifierCut, thawingPeriod: _thawingPeriod, createdAt: uint64(block.timestamp), - firstThawRequestId: bytes32(0), - lastThawRequestId: bytes32(0), - nThawRequests: 0, maxVerifierCutPending: _maxVerifierCut, thawingPeriodPending: _thawingPeriod }); @@ -636,30 +628,44 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); } - /** - * @dev Withdraw service provider tokens once the thawing period has passed. - * @param _serviceProvider Address of service provider to withdraw funds from - */ - function _withdraw(address _serviceProvider) private { - // Get tokens available for withdraw and update balance - ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; - uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; - require(tokensToWithdraw > 0, HorizonStakingInvalidZeroTokens()); - require( - block.timestamp >= sp.__DEPRECATED_tokensLockedUntil, - HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) - ); + function _thaw(address _serviceProvider, address _verifier, uint256 _tokens) private { + require(_tokens != 0, HorizonStakingInvalidZeroTokens()); + uint256 tokensAvailable = _getProviderTokensAvailable(_serviceProvider, _verifier); + require(tokensAvailable >= _tokens, HorizonStakingInsufficientTokensAvailable(tokensAvailable, _tokens)); - // Reset locked tokens - sp.__DEPRECATED_tokensLocked = 0; - sp.__DEPRECATED_tokensLockedUntil = 0; + Provision storage prov = _provisions[_serviceProvider][_verifier]; + uint256 thawingShares = prov.sharesThawing == 0 ? _tokens : (prov.sharesThawing * _tokens) / prov.tokensThawing; + uint64 thawingUntil = uint64(block.timestamp + uint256(prov.thawingPeriod)); - sp.tokensStaked = sp.tokensStaked - tokensToWithdraw; + // provision accounting + prov.tokensThawing = prov.tokensThawing + _tokens; + prov.sharesThawing = prov.sharesThawing + thawingShares; - // Return tokens to the service provider - _graphToken().pushTokens(_serviceProvider, tokensToWithdraw); + _createThawRequest(_serviceProvider, _verifier, _serviceProvider, thawingShares, thawingUntil); + emit ProvisionThawed(_serviceProvider, _verifier, _tokens); + } - emit StakeWithdrawn(_serviceProvider, tokensToWithdraw); + function _deprovision(address _serviceProvider, address _verifier, uint256 _nThawRequests) private { + Provision storage prov = _provisions[_serviceProvider][_verifier]; + + uint256 tokensThawed = 0; + uint256 sharesThawing = prov.sharesThawing; + uint256 tokensThawing = prov.tokensThawing; + (tokensThawed, tokensThawing, sharesThawing) = _fulfillThawRequests( + _serviceProvider, + _verifier, + _serviceProvider, + tokensThawing, + sharesThawing, + _nThawRequests + ); + + prov.tokens = prov.tokens - tokensThawed; + prov.sharesThawing = sharesThawing; + prov.tokensThawing = tokensThawing; + _serviceProviders[_serviceProvider].tokensProvisioned -= tokensThawed; + + emit TokensDeprovisioned(_serviceProvider, _verifier, tokensThawed); } function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) private { @@ -694,11 +700,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { require(delegation.shares >= _shares, HorizonStakingInvalidSharesAmount(delegation.shares, _shares)); uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; - uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); - pool.tokensThawing = pool.tokensThawing + tokens; - + uint64 thawingUntil = uint64(block.timestamp + uint256(_provisions[_serviceProvider][_verifier].thawingPeriod)); pool.shares = pool.shares - _shares; + pool.tokensThawing = pool.tokensThawing + tokens; pool.sharesThawing = pool.sharesThawing + thawingShares; delegation.shares = delegation.shares - _shares; @@ -710,25 +715,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { HorizonStakingInsufficientTokens(remainingTokens, MIN_DELEGATION) ); } - bytes32 thawRequestId = keccak256( - abi.encodePacked(_serviceProvider, _verifier, msg.sender, delegation.nextThawRequestNonce) - ); - delegation.nextThawRequestNonce += 1; - ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - thawRequest.shares = thawingShares; - thawRequest.thawingUntil = uint64( - block.timestamp + uint256(_provisions[_serviceProvider][_verifier].thawingPeriod) - ); - require(delegation.nThawRequests < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); - if (delegation.nThawRequests == 0) { - delegation.firstThawRequestId = thawRequestId; - } else { - _thawRequests[delegation.lastThawRequestId].next = thawRequestId; - } - delegation.lastThawRequestId = thawRequestId; - unchecked { - delegation.nThawRequests += 1; - } + + _createThawRequest(_serviceProvider, _verifier, msg.sender, thawingShares, thawingUntil); + emit TokensUndelegated(_serviceProvider, _verifier, msg.sender, tokens); } @@ -736,45 +725,34 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address _serviceProvider, address _verifier, address _newServiceProvider, - uint256 _minSharesForNewProvider + uint256 _minSharesForNewProvider, + uint256 _nThawRequests ) private { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); - Delegation storage delegation = pool.delegators[msg.sender]; - uint256 thawedTokens = 0; + uint256 tokensThawed = 0; uint256 sharesThawing = pool.sharesThawing; uint256 tokensThawing = pool.tokensThawing; - require(delegation.nThawRequests > 0, HorizonStakingNothingThawing()); - bytes32 thawRequestId = delegation.firstThawRequestId; - while (thawRequestId != bytes32(0)) { - ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - if (thawRequest.thawingUntil <= block.timestamp) { - uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; - tokensThawing = tokensThawing - tokens; - sharesThawing = sharesThawing - thawRequest.shares; - thawedTokens = thawedTokens + tokens; - delete _thawRequests[thawRequestId]; - delegation.firstThawRequestId = thawRequest.next; - delegation.nThawRequests -= 1; - if (delegation.nThawRequests == 0) { - delegation.lastThawRequestId = bytes32(0); - } - } else { - break; - } - thawRequestId = thawRequest.next; - } + (tokensThawed, tokensThawing, sharesThawing) = _fulfillThawRequests( + _serviceProvider, + _verifier, + msg.sender, + tokensThawing, + sharesThawing, + _nThawRequests + ); - pool.tokens = pool.tokens - thawedTokens; + pool.tokens = pool.tokens - tokensThawed; pool.sharesThawing = sharesThawing; pool.tokensThawing = tokensThawing; if (_newServiceProvider != address(0)) { - _delegate(_newServiceProvider, _verifier, thawedTokens, _minSharesForNewProvider); + _delegate(_newServiceProvider, _verifier, tokensThawed, _minSharesForNewProvider); } else { - _graphToken().pushTokens(msg.sender, thawedTokens); + _graphToken().pushTokens(msg.sender, tokensThawed); } - emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, thawedTokens); + + emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, tokensThawed); } function _setOperator(address _operator, address _verifier, bool _allowed) private { @@ -787,48 +765,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit OperatorSet(msg.sender, _operator, _verifier, _allowed); } - function _fulfillThawRequests(address _serviceProvider, address _verifier, uint256 _tokens) private { - require(_tokens != 0, HorizonStakingInvalidZeroTokens()); - Provision storage prov = _provisions[_serviceProvider][_verifier]; - uint256 tokensRemaining = _tokens; - uint256 sharesThawing = prov.sharesThawing; - uint256 tokensThawing = prov.tokensThawing; - while (tokensRemaining > 0) { - require(prov.nThawRequests > 0, HorizonStakingCannotFulfillThawRequest()); - bytes32 thawRequestId = prov.firstThawRequestId; - ThawRequest storage thawRequest = _thawRequests[thawRequestId]; - require(thawRequest.thawingUntil <= block.timestamp, HorizonStakingStillThawing(thawRequest.thawingUntil)); - uint256 thawRequestTokens = (thawRequest.shares * tokensThawing) / sharesThawing; - if (thawRequestTokens <= tokensRemaining) { - tokensRemaining = tokensRemaining - thawRequestTokens; - delete _thawRequests[thawRequestId]; - prov.firstThawRequestId = thawRequest.next; - prov.nThawRequests -= 1; - tokensThawing = tokensThawing - thawRequestTokens; - sharesThawing = sharesThawing - thawRequest.shares; - if (prov.nThawRequests == 0) { - prov.lastThawRequestId = bytes32(0); - } - } else { - // TODO check for potential rounding issues - uint256 sharesRemoved = (tokensRemaining * prov.sharesThawing) / prov.tokensThawing; - thawRequest.shares = thawRequest.shares - sharesRemoved; - tokensThawing = tokensThawing - tokensRemaining; - sharesThawing = sharesThawing - sharesRemoved; - } - emit ProvisionThawFulfilled( - _serviceProvider, - _verifier, - MathUtils.min(thawRequestTokens, tokensRemaining), - thawRequestId - ); - } - prov.sharesThawing = sharesThawing; - prov.tokensThawing = tokensThawing; - prov.tokens = prov.tokens - _tokens; - _serviceProviders[_serviceProvider].tokensProvisioned -= _tokens; - } - function _isAuthorized(address _operator, address _serviceProvider, address _verifier) private view returns (bool) { if (_operator == _serviceProvider) { return true; diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 951395b5b..8ececc9f5 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -7,6 +7,7 @@ import { IHorizonStakingBase } from "../interfaces/internal/IHorizonStakingBase. import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; +import { LinkedList } from "../libraries/LinkedList.sol"; import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { GraphUpgradeable } from "@graphprotocol/contracts/contracts/upgrades/GraphUpgradeable.sol"; @@ -27,8 +28,13 @@ abstract contract HorizonStakingBase is IHorizonStakingTypes, IHorizonStakingBase { + using LinkedList for LinkedList.List; + address internal immutable SUBGRAPH_DATA_SERVICE_ADDRESS; + /// @dev Maximum number of simultaneous stake thaw requests (per provision) or undelegations (per delegation) + uint256 private constant MAX_THAW_REQUESTS = 100; + constructor(address controller, address subgraphDataServiceAddress) Managed(controller) { SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; } @@ -68,7 +74,6 @@ abstract contract HorizonStakingBase is ServiceProviderInternal storage spInternal = _serviceProviders[serviceProvider]; sp.tokensStaked = spInternal.tokensStaked; sp.tokensProvisioned = spInternal.tokensProvisioned; - sp.nextThawRequestNonce = spInternal.nextThawRequestNonce; return sp; } @@ -144,12 +149,15 @@ abstract contract HorizonStakingBase is * @param verifier The verifier address for which the tokens are provisioned */ function getThawedTokens(address serviceProvider, address verifier) external view returns (uint256) { - Provision storage prov = _provisions[serviceProvider][verifier]; - if (prov.nThawRequests == 0) { + LinkedList.List storage thawRequestList = _thawRequestLists[serviceProvider][verifier][serviceProvider]; + if (thawRequestList.count == 0) { return 0; } - bytes32 thawRequestId = prov.firstThawRequestId; + uint256 tokens = 0; + Provision storage prov = _provisions[serviceProvider][verifier]; + + bytes32 thawRequestId = thawRequestList.head; while (thawRequestId != bytes32(0)) { ThawRequest storage thawRequest = _thawRequests[thawRequestId]; if (thawRequest.thawingUntil <= block.timestamp) { @@ -173,6 +181,87 @@ abstract contract HorizonStakingBase is emit StakeDeposited(_serviceProvider, _tokens); } + function _createThawRequest( + address _serviceProvider, + address _verifier, + address _owner, + uint256 _shares, + uint64 _thawingUntil + ) internal { + LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; + require(thawRequestList.count < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); + + bytes32 thawRequestId = keccak256(abi.encodePacked(_serviceProvider, _verifier, _owner, thawRequestList.nonce)); + _thawRequests[thawRequestId] = ThawRequest({ shares: _shares, thawingUntil: _thawingUntil, next: bytes32(0) }); + + if (thawRequestList.count != 0) _thawRequests[thawRequestList.tail].next = thawRequestId; + thawRequestList.add(thawRequestId); + + emit ThawRequestCreated(_serviceProvider, _verifier, _owner, _shares, _thawingUntil, thawRequestId); + } + + function _fulfillThawRequests( + address _serviceProvider, + address _verifier, + address _owner, + uint256 _tokensThawing, + uint256 _sharesThawing, + uint256 _nThawRequests + ) internal returns (uint256, uint256, uint256) { + LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; + require(thawRequestList.count > 0, HorizonStakingNothingThawing()); + + uint256 tokensThawed = 0; + (uint256 thawRequestsFulfilled, bytes memory data) = thawRequestList.traverse( + _getNextThawRequest, + _fulfillThawRequest, + _deleteThawRequest, + abi.encode(tokensThawed, _tokensThawing, _sharesThawing), + _nThawRequests + ); + + (tokensThawed, _tokensThawing, _sharesThawing) = abi.decode(data, (uint256, uint256, uint256)); + emit ThawRequestsFulfilled(_serviceProvider, _verifier, _owner, thawRequestsFulfilled, tokensThawed); + return (tokensThawed, _tokensThawing, _sharesThawing); + } + + function _fulfillThawRequest( + bytes32 _thawRequestId, + bytes memory _acc + ) internal returns (bool, bool, bytes memory) { + ThawRequest storage thawRequest = _thawRequests[_thawRequestId]; + + // early exit + if (thawRequest.thawingUntil > block.timestamp) { + return (true, false, LinkedList.NULL_BYTES); + } + + // decode + (uint256 tokensThawed, uint256 tokensThawing, uint256 sharesThawing) = abi.decode( + _acc, + (uint256, uint256, uint256) + ); + + // process + uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; + tokensThawing = tokensThawing - tokens; + sharesThawing = sharesThawing - thawRequest.shares; + tokensThawed = tokensThawed + tokens; + emit ThawRequestFulfilled(_thawRequestId, tokens, thawRequest.shares, thawRequest.thawingUntil); + + // encode + _acc = abi.encode(tokensThawed, tokensThawing, sharesThawing); + return (false, true, _acc); + } + + function _deleteThawRequest(bytes32 _thawRequestId) internal { + delete _thawRequests[_thawRequestId]; + } + + function _getNextThawRequest(bytes32 _thawRequestId) private view returns (bytes32) { + return _thawRequests[_thawRequestId].next; + } + function _getDelegationPool( address _serviceProvider, address _verifier diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index ffe82ab30..8d147866a 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -6,6 +6,8 @@ import { IHorizonStakingExtension } from "../interfaces/internal/IHorizonStaking import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; +import { LinkedList } from "../libraries/LinkedList.sol"; + // TODO: create custom var-name-mixedcase /* solhint-disable var-name-mixedcase */ @@ -137,6 +139,9 @@ abstract contract HorizonStakingV1Storage { mapping(bytes32 thawRequestId => IHorizonStakingTypes.ThawRequest thawRequest) internal _thawRequests; + mapping(address serviceProvider => mapping(address verifier => mapping(address owner => LinkedList.List list))) + internal _thawRequestLists; + // service provider => verifier => operator => authorized mapping(address serviceProvider => mapping(address verifier => mapping(address operator => bool authorized))) internal _operatorAuth; diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index 2d951261d..fa73c9643 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -1,4 +1,4 @@ -// import '@nomicfoundation/hardhat-foundry' +import '@nomicfoundation/hardhat-foundry' import '@nomicfoundation/hardhat-toolbox' import 'hardhat-storage-layout' import 'hardhat-contract-sizer' From 1c6202713d41a9cee3f2c22194ae8d3aa0e2acab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 28 May 2024 12:16:36 -0300 Subject: [PATCH 080/277] feat: make fees extension only one type of payment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServiceFees.sol | 41 +++---- .../extensions/DataServiceFeesStorage.sol | 7 +- .../interfaces/IDataServiceFees.sol | 12 +- .../internal/IHorizonStakingBase.sol | 8 ++ .../internal/IHorizonStakingMain.sol | 8 +- .../contracts/libraries/LinkedList.sol | 6 +- .../contracts/staking/HorizonStaking.sol | 116 ++++++++++++++++-- .../contracts/staking/HorizonStakingBase.sol | 90 ++------------ packages/horizon/test/data-service/DataS.sol | 83 +++++++++++++ packages/horizon/test/data-service/test.t.sol | 30 +++++ .../test/staking/delegation/undelegate.t.sol | 6 +- .../test/staking/delegation/withdraw.t.sol | 8 +- .../test/staking/provision/reprovision.t.sol | 2 +- packages/horizon/test/staking/thaw/thaw.t.sol | 13 +- .../contracts/SubgraphService.sol | 4 +- packages/subgraph-service/hardhat.config.ts | 28 ++--- .../test/mocks/MockHorizonStaking.sol | 3 - 17 files changed, 289 insertions(+), 176 deletions(-) create mode 100644 packages/horizon/test/data-service/DataS.sol create mode 100644 packages/horizon/test/data-service/test.t.sol diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index b416bcf69..0e418503d 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.26; import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; -import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; import { ProvisionTracker } from "../libraries/ProvisionTracker.sol"; import { LinkedList } from "../../libraries/LinkedList.sol"; @@ -14,19 +13,14 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat using ProvisionTracker for mapping(address => uint256); using LinkedList for LinkedList.List; - function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external virtual { - _releaseStake(feeType, msg.sender, n); + function releaseStake(uint256 n) external virtual override { + _releaseStake(msg.sender, n); } - function _lockStake( - IGraphPayments.PaymentTypes _feeType, - address _serviceProvider, - uint256 _tokens, - uint256 _unlockTimestamp - ) internal { - feesProvisionTracker[_feeType].lock(_graphStaking(), _serviceProvider, _tokens, maximumDelegationRatio); + function _lockStake(address _serviceProvider, uint256 _tokens, uint256 _unlockTimestamp) internal { + feesProvisionTracker.lock(_graphStaking(), _serviceProvider, _tokens, maximumDelegationRatio); - LinkedList.List storage claimsList = claimsLists[_feeType][_serviceProvider]; + LinkedList.List storage claimsList = claimsLists[_serviceProvider]; // Save item and add to list bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); @@ -40,25 +34,25 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat if (claimsList.count != 0) claims[claimsList.tail].nextClaim = claimId; claimsList.add(claimId); - emit StakeClaimLocked(_serviceProvider, _feeType, claimId, _tokens, _unlockTimestamp); + emit StakeClaimLocked(_serviceProvider, claimId, _tokens, _unlockTimestamp); } /// @notice Release expired stake claims for a service provider /// @param _n The number of stake claims to release, or 0 to release all - function _releaseStake(IGraphPayments.PaymentTypes _feeType, address _serviceProvider, uint256 _n) internal { - LinkedList.List storage claimsList = claimsLists[_feeType][_serviceProvider]; + function _releaseStake(address _serviceProvider, uint256 _n) internal { + LinkedList.List storage claimsList = claimsLists[_serviceProvider]; (uint256 claimsReleased, bytes memory data) = claimsList.traverse( _getNextStakeClaim, _processStakeClaim, _deleteStakeClaim, - abi.encode(0), + abi.encode(0, _serviceProvider), _n ); - emit StakeClaimsReleased(_serviceProvider, _feeType, claimsReleased, abi.decode(data, (uint256))); + emit StakeClaimsReleased(_serviceProvider, claimsReleased, abi.decode(data, (uint256))); } - function _processStakeClaim(bytes32 _claimId, bytes memory acc) private returns (bool, bool, bytes memory) { + function _processStakeClaim(bytes32 _claimId, bytes memory _acc) private returns (bool, bool, bytes memory) { StakeClaim memory claim = _getStakeClaim(_claimId); // early exit @@ -67,18 +61,15 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat } // decode - (IGraphPayments.PaymentTypes _feeType, address _serviceProvider) = abi.decode( - acc, - (IGraphPayments.PaymentTypes, address) - ); + (uint256 tokensClaimed, address serviceProvider) = abi.decode(_acc, (uint256, address)); // process - feesProvisionTracker[_feeType].release(_serviceProvider, claim.tokens); - emit StakeClaimReleased(_serviceProvider, _feeType, _claimId, claim.tokens, claim.releaseAt); + feesProvisionTracker.release(serviceProvider, claim.tokens); + emit StakeClaimReleased(serviceProvider, _claimId, claim.tokens, claim.releaseAt); // encode - acc = abi.encode(abi.decode(acc, (uint256)) + claim.tokens); - return (false, true, acc); + _acc = abi.encode(tokensClaimed + claim.tokens, serviceProvider); + return (false, true, _acc); } function _deleteStakeClaim(bytes32 _claimId) private { diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 7e867c35e..57e178e86 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -2,20 +2,17 @@ pragma solidity 0.8.26; import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; -import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; import { LinkedList } from "../../libraries/LinkedList.sol"; abstract contract DataServiceFeesV1Storage { - mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => uint256 tokens)) - public feesProvisionTracker; + mapping(address serviceProvider => uint256 tokens) public feesProvisionTracker; /// @notice List of all locked stake claims to be released to service providers mapping(bytes32 claimId => IDataServiceFees.StakeClaim claim) public claims; /// @notice Service providers registered in the data service - mapping(IGraphPayments.PaymentTypes feeType => mapping(address serviceProvider => LinkedList.List list)) - public claimsLists; + mapping(address serviceProvider => LinkedList.List list) public claimsLists; /// @dev Gap to allow adding variables in future upgrades uint256[50] private __gap; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index 9e39e62fd..cab7e9998 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; -import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; interface IDataServiceFees is IDataService { /// A locked stake claim to be released to a service provider @@ -19,26 +18,19 @@ interface IDataServiceFees is IDataService { event StakeClaimLocked( address indexed serviceProvider, - IGraphPayments.PaymentTypes indexed feeType, bytes32 indexed claimId, uint256 tokens, uint256 unlockTimestamp ); event StakeClaimReleased( address indexed serviceProvider, - IGraphPayments.PaymentTypes indexed feeType, bytes32 indexed claimId, uint256 tokens, uint256 releaseAt ); - event StakeClaimsReleased( - address indexed serviceProvider, - IGraphPayments.PaymentTypes indexed feeType, - uint256 claimsCount, - uint256 tokensReleased - ); + event StakeClaimsReleased(address indexed serviceProvider, uint256 claimsCount, uint256 tokensReleased); error DataServiceFeesClaimNotFound(bytes32 claimId); - function releaseStake(IGraphPayments.PaymentTypes feeType, uint256 n) external; + function releaseStake(uint256 n) external; } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index 76ad132aa..c8dea3da6 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -5,6 +5,8 @@ pragma solidity 0.8.26; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; import { IGraphPayments } from "../IGraphPayments.sol"; +import { LinkedList } from "../../libraries/LinkedList.sol"; + interface IHorizonStakingBase { /** * @dev Emitted when `serviceProvider` stakes `tokens` amount. @@ -86,4 +88,10 @@ interface IHorizonStakingBase { function getIdleStake(address serviceProvider) external view returns (uint256 tokens); function getProviderTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); + + function getThawRequestList( + address serviceProvider, + address verifier, + address owner + ) external view returns (LinkedList.List memory); } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index ced1957b9..d11d958b8 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -163,7 +163,7 @@ interface IHorizonStakingMain is IHorizonStakingBase { ) external; // initiate a thawing to remove tokens from a provision - function thaw(address serviceProvider, address verifier, uint256 tokens) external; + function thaw(address serviceProvider, address verifier, uint256 tokens) external returns (bytes32); // add more tokens from idle stake to an existing provision function addToProvision(address serviceProvider, address verifier, uint256 tokens) external; @@ -176,8 +176,8 @@ interface IHorizonStakingMain is IHorizonStakingBase { address serviceProvider, address oldVerifier, address newVerifier, - uint256 nThawRequests, - uint256 tokens + uint256 tokens, + uint256 nThawRequests ) external; // moves thawed stake back to the owner's account - stake is removed from the protocol @@ -187,7 +187,7 @@ interface IHorizonStakingMain is IHorizonStakingBase { function delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) external; // undelegate (thaw) delegated tokens from a provision - function undelegate(address serviceProvider, address verifier, uint256 shares) external; + function undelegate(address serviceProvider, address verifier, uint256 shares) external returns (bytes32); // withdraw delegated tokens after thawing function withdrawDelegated( diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index 28ced852a..d58d3f5cd 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -5,15 +5,15 @@ pragma solidity 0.8.26; library LinkedList { using LinkedList for List; - error LinkedListEmptyList(); - - bytes internal constant NULL_BYTES = bytes(""); struct List { bytes32 head; bytes32 tail; uint256 nonce; uint256 count; } + bytes internal constant NULL_BYTES = bytes(""); + + error LinkedListEmptyList(); function add(List storage self, bytes32 id) internal { self.tail = id; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 2986f7c30..e72027cbb 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -36,6 +36,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /// @dev Fixed point precision uint256 private constant FIXED_POINT_PRECISION = 1e18; + /// @dev Maximum number of simultaneous stake thaw requests (per provision) or undelegations (per delegation) + uint256 private constant MAX_THAW_REQUESTS = 100; + /// @dev Minimum amount of delegation to prevent rounding attacks. /// TODO: remove this after L2 transfer tool for delegation is removed /// (delegation on L2 has its own slippage protection) @@ -199,8 +202,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address verifier, uint256 tokens - ) external override notPaused onlyAuthorized(serviceProvider, verifier) { - _thaw(serviceProvider, verifier, tokens); + ) external override notPaused onlyAuthorized(serviceProvider, verifier) returns (bytes32) { + return _thaw(serviceProvider, verifier, tokens); } // moves thawed stake from a provision back into the provider's available stake @@ -226,8 +229,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address oldVerifier, address newVerifier, - uint256 nThawRequests, - uint256 tokens + uint256 tokens, + uint256 nThawRequests ) external override @@ -293,8 +296,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // undelegate tokens from a service provider // the shares are burned and replaced with shares in the thawing pool - function undelegate(address serviceProvider, address verifier, uint256 shares) external override notPaused { - _undelegate(serviceProvider, verifier, shares); + function undelegate( + address serviceProvider, + address verifier, + uint256 shares + ) external override notPaused returns (bytes32) { + return _undelegate(serviceProvider, verifier, shares); } function withdrawDelegated( @@ -628,7 +635,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); } - function _thaw(address _serviceProvider, address _verifier, uint256 _tokens) private { + function _thaw(address _serviceProvider, address _verifier, uint256 _tokens) private returns (bytes32) { require(_tokens != 0, HorizonStakingInvalidZeroTokens()); uint256 tokensAvailable = _getProviderTokensAvailable(_serviceProvider, _verifier); require(tokensAvailable >= _tokens, HorizonStakingInsufficientTokensAvailable(tokensAvailable, _tokens)); @@ -641,8 +648,15 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { prov.tokensThawing = prov.tokensThawing + _tokens; prov.sharesThawing = prov.sharesThawing + thawingShares; - _createThawRequest(_serviceProvider, _verifier, _serviceProvider, thawingShares, thawingUntil); + bytes32 thawRequestId = _createThawRequest( + _serviceProvider, + _verifier, + _serviceProvider, + thawingShares, + thawingUntil + ); emit ProvisionThawed(_serviceProvider, _verifier, _tokens); + return thawRequestId; } function _deprovision(address _serviceProvider, address _verifier, uint256 _nThawRequests) private { @@ -693,7 +707,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit TokensDelegated(_serviceProvider, _verifier, msg.sender, _tokens); } - function _undelegate(address _serviceProvider, address _verifier, uint256 _shares) private { + function _undelegate(address _serviceProvider, address _verifier, uint256 _shares) private returns (bytes32) { require(_shares > 0, HorizonStakingInvalidZeroShares()); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); Delegation storage delegation = pool.delegators[msg.sender]; @@ -716,9 +730,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { ); } - _createThawRequest(_serviceProvider, _verifier, msg.sender, thawingShares, thawingUntil); + bytes32 thawRequestId = _createThawRequest( + _serviceProvider, + _verifier, + msg.sender, + thawingShares, + thawingUntil + ); emit TokensUndelegated(_serviceProvider, _verifier, msg.sender, tokens); + return thawRequestId; } function _withdrawDelegated( @@ -755,6 +776,81 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, tokensThawed); } + function _createThawRequest( + address _serviceProvider, + address _verifier, + address _owner, + uint256 _shares, + uint64 _thawingUntil + ) private returns (bytes32) { + LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; + require(thawRequestList.count < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); + + bytes32 thawRequestId = keccak256(abi.encodePacked(_serviceProvider, _verifier, _owner, thawRequestList.nonce)); + _thawRequests[thawRequestId] = ThawRequest({ shares: _shares, thawingUntil: _thawingUntil, next: bytes32(0) }); + + if (thawRequestList.count != 0) _thawRequests[thawRequestList.tail].next = thawRequestId; + thawRequestList.add(thawRequestId); + + emit ThawRequestCreated(_serviceProvider, _verifier, _owner, _shares, _thawingUntil, thawRequestId); + return thawRequestId; + } + + function _fulfillThawRequests( + address _serviceProvider, + address _verifier, + address _owner, + uint256 _tokensThawing, + uint256 _sharesThawing, + uint256 _nThawRequests + ) private returns (uint256, uint256, uint256) { + LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; + require(thawRequestList.count > 0, HorizonStakingNothingThawing()); + + uint256 tokensThawed = 0; + (uint256 thawRequestsFulfilled, bytes memory data) = thawRequestList.traverse( + _getNextThawRequest, + _fulfillThawRequest, + _deleteThawRequest, + abi.encode(tokensThawed, _tokensThawing, _sharesThawing), + _nThawRequests + ); + + (tokensThawed, _tokensThawing, _sharesThawing) = abi.decode(data, (uint256, uint256, uint256)); + emit ThawRequestsFulfilled(_serviceProvider, _verifier, _owner, thawRequestsFulfilled, tokensThawed); + return (tokensThawed, _tokensThawing, _sharesThawing); + } + + function _fulfillThawRequest(bytes32 _thawRequestId, bytes memory _acc) private returns (bool, bool, bytes memory) { + ThawRequest storage thawRequest = _thawRequests[_thawRequestId]; + + // early exit + if (thawRequest.thawingUntil > block.timestamp) { + return (true, false, LinkedList.NULL_BYTES); + } + + // decode + (uint256 tokensThawed, uint256 tokensThawing, uint256 sharesThawing) = abi.decode( + _acc, + (uint256, uint256, uint256) + ); + + // process + uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; + tokensThawing = tokensThawing - tokens; + sharesThawing = sharesThawing - thawRequest.shares; + tokensThawed = tokensThawed + tokens; + emit ThawRequestFulfilled(_thawRequestId, tokens, thawRequest.shares, thawRequest.thawingUntil); + + // encode + _acc = abi.encode(tokensThawed, tokensThawing, sharesThawing); + return (false, true, _acc); + } + + function _deleteThawRequest(bytes32 _thawRequestId) private { + delete _thawRequests[_thawRequestId]; + } + function _setOperator(address _operator, address _verifier, bool _allowed) private { require(_operator != msg.sender, HorizonStakingCallerIsServiceProvider()); if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 8ececc9f5..27b8e10e3 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -32,9 +32,6 @@ abstract contract HorizonStakingBase is address internal immutable SUBGRAPH_DATA_SERVICE_ADDRESS; - /// @dev Maximum number of simultaneous stake thaw requests (per provision) or undelegations (per delegation) - uint256 private constant MAX_THAW_REQUESTS = 100; - constructor(address controller, address subgraphDataServiceAddress) Managed(controller) { SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; } @@ -107,6 +104,14 @@ abstract contract HorizonStakingBase is return _thawRequests[thawRequestId]; } + function getThawRequestList( + address serviceProvider, + address verifier, + address owner + ) external view returns (LinkedList.List memory) { + return _thawRequestLists[serviceProvider][verifier][owner]; + } + function getProvision(address serviceProvider, address verifier) external view override returns (Provision memory) { return _provisions[serviceProvider][verifier]; } @@ -181,84 +186,7 @@ abstract contract HorizonStakingBase is emit StakeDeposited(_serviceProvider, _tokens); } - function _createThawRequest( - address _serviceProvider, - address _verifier, - address _owner, - uint256 _shares, - uint64 _thawingUntil - ) internal { - LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; - require(thawRequestList.count < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); - - bytes32 thawRequestId = keccak256(abi.encodePacked(_serviceProvider, _verifier, _owner, thawRequestList.nonce)); - _thawRequests[thawRequestId] = ThawRequest({ shares: _shares, thawingUntil: _thawingUntil, next: bytes32(0) }); - - if (thawRequestList.count != 0) _thawRequests[thawRequestList.tail].next = thawRequestId; - thawRequestList.add(thawRequestId); - - emit ThawRequestCreated(_serviceProvider, _verifier, _owner, _shares, _thawingUntil, thawRequestId); - } - - function _fulfillThawRequests( - address _serviceProvider, - address _verifier, - address _owner, - uint256 _tokensThawing, - uint256 _sharesThawing, - uint256 _nThawRequests - ) internal returns (uint256, uint256, uint256) { - LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; - require(thawRequestList.count > 0, HorizonStakingNothingThawing()); - - uint256 tokensThawed = 0; - (uint256 thawRequestsFulfilled, bytes memory data) = thawRequestList.traverse( - _getNextThawRequest, - _fulfillThawRequest, - _deleteThawRequest, - abi.encode(tokensThawed, _tokensThawing, _sharesThawing), - _nThawRequests - ); - - (tokensThawed, _tokensThawing, _sharesThawing) = abi.decode(data, (uint256, uint256, uint256)); - emit ThawRequestsFulfilled(_serviceProvider, _verifier, _owner, thawRequestsFulfilled, tokensThawed); - return (tokensThawed, _tokensThawing, _sharesThawing); - } - - function _fulfillThawRequest( - bytes32 _thawRequestId, - bytes memory _acc - ) internal returns (bool, bool, bytes memory) { - ThawRequest storage thawRequest = _thawRequests[_thawRequestId]; - - // early exit - if (thawRequest.thawingUntil > block.timestamp) { - return (true, false, LinkedList.NULL_BYTES); - } - - // decode - (uint256 tokensThawed, uint256 tokensThawing, uint256 sharesThawing) = abi.decode( - _acc, - (uint256, uint256, uint256) - ); - - // process - uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; - tokensThawing = tokensThawing - tokens; - sharesThawing = sharesThawing - thawRequest.shares; - tokensThawed = tokensThawed + tokens; - emit ThawRequestFulfilled(_thawRequestId, tokens, thawRequest.shares, thawRequest.thawingUntil); - - // encode - _acc = abi.encode(tokensThawed, tokensThawing, sharesThawing); - return (false, true, _acc); - } - - function _deleteThawRequest(bytes32 _thawRequestId) internal { - delete _thawRequests[_thawRequestId]; - } - - function _getNextThawRequest(bytes32 _thawRequestId) private view returns (bytes32) { + function _getNextThawRequest(bytes32 _thawRequestId) internal view returns (bytes32) { return _thawRequests[_thawRequestId].next; } diff --git a/packages/horizon/test/data-service/DataS.sol b/packages/horizon/test/data-service/DataS.sol new file mode 100644 index 000000000..3ed3aa3ba --- /dev/null +++ b/packages/horizon/test/data-service/DataS.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; +import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; +import { IDataServiceFees } from "../../contracts/data-service/interfaces/IDataServiceFees.sol"; + +import { LinkedList } from "../../contracts/libraries/LinkedList.sol"; +import "forge-std/console.sol"; + +contract DataS { + using LinkedList for LinkedList.List; + struct StakeClaim { + uint256 tokens; + uint256 releaseAt; + bytes32 nextClaim; + } + + mapping(bytes32 claimId => StakeClaim tokens) public claims; + /// @notice Service providers registered in the data service + mapping(address serviceProvider => LinkedList.List list) public claimsLists2; + + constructor() {} + + function lockStake(address sp, uint256 tokens, uint256 unlock) external { + _lockStake(sp, tokens, unlock); + } + + function releaseStake2(address _serviceProvider, uint256 _n) external { + LinkedList.List storage claimsList2 = claimsLists2[_serviceProvider]; + (uint256 count, bytes memory acc) = claimsList2.traverse( + _getNextStakeClaim, + _processStakeClaim, + _deleteStakeClaim, + abi.encode(0), + _n + ); + + uint256 tokens = abi.decode(acc, (uint256)); + + console.log("count: %s", count); + console.log("tokens accumualted: %s", tokens); + } + + function _lockStake(address _serviceProvider, uint256 _tokens, uint256 _unlockTimestamp) internal { + LinkedList.List storage claimsList = claimsLists2[_serviceProvider]; + bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); + claims[claimId] = StakeClaim({ tokens: _tokens, releaseAt: _unlockTimestamp, nextClaim: bytes32(0) }); + console.logBytes32(claimId); + claims[claimsList.tail].nextClaim = claimId; + + claimsList.tail = claimId; + claimsList.nonce += 1; + if (claimsList.head == bytes32(0)) claimsList.head = claimId; + } + + function _buildStakeClaimId(address _serviceProvider, uint256 _nonce) private view returns (bytes32) { + return keccak256(abi.encodePacked(address(this), _serviceProvider, _nonce)); + } + + function _getStakeClaim(bytes32 _claimId) private view returns (StakeClaim memory) { + StakeClaim memory claim = claims[_claimId]; + return claim; + } + + function _getNextStakeClaim(bytes32 _claimId) private view returns (bytes32) { + StakeClaim memory claim = claims[_claimId]; + return claim.nextClaim; + } + + function _deleteStakeClaim(bytes32 _claimId) private { + delete claims[_claimId]; + } + + function _processStakeClaim( + bytes32 _claimId, + bytes memory acc_ + ) private returns (bool, bool, bytes memory) { + StakeClaim memory claim = _getStakeClaim(_claimId); + if (block.timestamp < claim.releaseAt) return (true, false, LinkedList.NULL_BYTES); + + uint256 tokensAcc = abi.decode(acc_, (uint256)); + return (block.timestamp < claim.releaseAt, true, abi.encode(tokensAcc + claim.tokens)); + } +} diff --git a/packages/horizon/test/data-service/test.t.sol b/packages/horizon/test/data-service/test.t.sol new file mode 100644 index 000000000..ddedca6c7 --- /dev/null +++ b/packages/horizon/test/data-service/test.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { DataS } from "./DataS.sol"; + +// import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaking.t.sol"; + +contract DataServiceTest is Test { + DataS ds = new DataS(); + address sp1 = makeAddr("sp1"); + + function setUp() public { + ds.lockStake(sp1, 10 wei, block.timestamp + 100); + ds.lockStake(sp1, 1 wei, block.timestamp + 200); + ds.lockStake(sp1, 1 wei, block.timestamp + 300); + ds.lockStake(sp1, 1 wei, block.timestamp + 400); + vm.warp(block.timestamp + 2000); + console.log("done setup"); + } + + function test_test() public { + assertTrue(true); + } + + function test_release() public { + ds.releaseStake2(sp1, 0); + } +} diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index e3b355c30..5c6bab44c 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -5,6 +5,8 @@ import "forge-std/Test.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; + contract HorizonStakingUndelegateTest is HorizonStakingTest { function testUndelegate_Tokens( @@ -17,8 +19,8 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { Delegation memory delegation = _getDelegation(); _undelegate(delegation.shares); - Delegation memory thawingDelegation = _getDelegation(); - ThawRequest memory thawRequest = staking.getThawRequest(thawingDelegation.lastThawRequestId); + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceAddress, users.delegator); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); assertEq(thawRequest.shares, delegation.shares); } diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 2db1a4237..01840874b 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -5,6 +5,8 @@ import "forge-std/Test.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; + contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { modifier useUndelegate(uint256 shares) { @@ -26,7 +28,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { } function _withdrawDelegated() private { - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0x0), 0); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0x0), 0, 0); } function _expectedTokensFromThawRequest(ThawRequest memory thawRequest) private view returns (uint256) { @@ -44,8 +46,8 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useDelegation(delegationAmount) useUndelegate(withdrawShares) { - Delegation memory thawingDelegation = _getDelegation(); - ThawRequest memory thawRequest = staking.getThawRequest(thawingDelegation.lastThawRequestId); + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceAddress, users.delegator); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); skip(thawRequest.thawingUntil + 1); diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 8a7d17d6a..78a7a50ac 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -10,7 +10,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { address private newDataService = makeAddr("newDataService"); function _reprovision(uint256 amount) private { - staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, amount); + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, amount, 0); } function testReprovision_MovingTokens( diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index 3d2ce4b90..ec2d9e0e5 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -7,7 +7,6 @@ import { IHorizonStakingTypes } from "../../../contracts/interfaces/internal/IHo import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingThawTest is HorizonStakingTest { - function testThaw_Tokens( uint256 amount, uint64 thawingPeriod, @@ -15,12 +14,12 @@ contract HorizonStakingThawTest is HorizonStakingTest { ) public useIndexer useProvision(amount, 0, thawingPeriod) { thawAmount = bound(thawAmount, 1, amount); bytes32 expectedThawRequestId = keccak256( - abi.encodePacked(users.indexer, subgraphDataServiceAddress, uint256(0)) + abi.encodePacked(users.indexer, subgraphDataServiceAddress, users.indexer, uint256(0)) ); bytes32 thawRequestId = _createThawRequest(thawAmount); assertEq(thawRequestId, expectedThawRequestId); - ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + ThawRequest memory thawRequest = staking.getThawRequest(expectedThawRequestId); assertEq(thawRequest.shares, thawAmount); assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); } @@ -52,7 +51,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { uint64 thawingPeriod ) public useOperator useProvision(amount, 0, thawingPeriod) { bytes32 thawRequestId = _createThawRequest(amount); - + ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); assertEq(thawRequest.shares, amount); assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); @@ -64,7 +63,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { ) public useIndexer useProvision(amount, 0, thawingPeriod) { vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingNotAuthorized(address,address,address)", + "HorizonStakingNotAuthorized(address,address,address)", users.operator, users.indexer, subgraphDataServiceAddress @@ -96,7 +95,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { // vm.assume(thawAmount > 0); // vm.assume(amount / (MAX_THAW_REQUESTS + 1) > thawAmount); thawAmount = bound(thawAmount, 1, amount / (MAX_THAW_REQUESTS + 1)); - + for (uint256 i = 0; i < 100; i++) { _createThawRequest(thawAmount); } @@ -115,4 +114,4 @@ contract HorizonStakingThawTest is HorizonStakingTest { vm.expectRevert(expectedError); _createThawRequest(thawAmount); } -} \ No newline at end of file +} diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 9a66c7916..5a5598b47 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -216,7 +216,7 @@ contract SubgraphService is bytes32 subgraphDeploymentId = allocations.get(allocationId).subgraphDeploymentId; // release expired stake claims - _releaseStake(IGraphPayments.PaymentTypes.QueryFee, indexer, 0); + _releaseStake(indexer, 0); // Collect from GraphPayments PaymentCuts memory queryFeePaymentCuts = _getQueryFeePaymentCuts(subgraphDeploymentId); @@ -240,7 +240,7 @@ contract SubgraphService is // lock stake as economic security for fees uint256 tokensToLock = tokensCollected * stakeToFeesRatio; uint256 unlockTimestamp = block.timestamp + _disputeManager().getDisputePeriod(); - _lockStake(IGraphPayments.PaymentTypes.QueryFee, indexer, tokensToLock, unlockTimestamp); + _lockStake(indexer, tokensToLock, unlockTimestamp); // calculate service and curator cuts tokensCurators = tokensCollected.mulPPMRoundUp(queryFeePaymentCuts.curationCut); diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts index 1db083d76..a8e05c779 100644 --- a/packages/subgraph-service/hardhat.config.ts +++ b/packages/subgraph-service/hardhat.config.ts @@ -1,4 +1,4 @@ -// import '@nomicfoundation/hardhat-foundry' +import '@nomicfoundation/hardhat-foundry' import '@nomicfoundation/hardhat-toolbox' import 'hardhat-contract-sizer' import 'hardhat-storage-layout' @@ -8,26 +8,14 @@ import { HardhatUserConfig } from 'hardhat/config' const config: HardhatUserConfig = { solidity: { - compilers: [ - { - version: '0.8.26', - settings: { - viaIR: true, - optimizer: { - enabled: true, - runs: 200, - }, - metadata: { - useLiteralContent: true, - }, - outputSelection: { - '*': { - '*': ['storageLayout', 'metadata'], - }, - }, - }, + version: '0.8.26', + settings: { + viaIR: true, + optimizer: { + enabled: true, + runs: 200, }, - ], + }, }, paths: { artifacts: './build/contracts', diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index c8ee45799..d7b205c5c 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -30,9 +30,6 @@ contract MockHorizonStaking { maxVerifierCut: maxVerifierCut, thawingPeriod: thawingPeriod, createdAt: uint64(block.timestamp), - firstThawRequestId: bytes32(0), - lastThawRequestId: bytes32(0), - nThawRequests: 0, maxVerifierCutPending: maxVerifierCut, thawingPeriodPending: thawingPeriod }); From c11b31e5afe3f7b57567d165f467ac801a125890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 28 May 2024 14:18:52 -0300 Subject: [PATCH 081/277] feat: make subgraph service and graph payments upgradeable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../DataServicePausableUpgradeable.sol | 36 ++++ .../contracts/payments/GraphPayments.sol | 21 +- .../payments/GraphPaymentsStorage.sol | 7 - packages/horizon/package.json | 1 + packages/horizon/remappings.txt | 1 + .../contracts/DisputeManager.sol | 26 ++- .../contracts/SubgraphService.sol | 29 +-- .../contracts/utilities/AllocationManager.sol | 14 +- .../utilities/AttestationManager.sol | 7 +- packages/subgraph-service/package.json | 1 + packages/subgraph-service/remappings.txt | 2 + .../test/DisputeManager.t.sol | 187 +++++++++--------- 12 files changed, 189 insertions(+), 143 deletions(-) create mode 100644 packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol delete mode 100644 packages/horizon/contracts/payments/GraphPaymentsStorage.sol diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol new file mode 100644 index 000000000..ad60c4c9f --- /dev/null +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { IDataServicePausable } from "../interfaces/IDataServicePausable.sol"; + +import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; +import { DataService } from "../DataService.sol"; + +abstract contract DataServicePausableUpgradeable is PausableUpgradeable, DataService, IDataServicePausable { + mapping(address pauseGuardian => bool allowed) public pauseGuardians; + + modifier onlyPauseGuardian() { + require(pauseGuardians[msg.sender], DataServicePausableNotPauseGuardian(msg.sender)); + _; + } + + function pause() public onlyPauseGuardian whenNotPaused { + _pause(); + } + + function unpause() public onlyPauseGuardian whenPaused { + _unpause(); + } + + function __DataServicePausable_init() internal { + __Pausable_init_unchained(); + __DataServicePausable_init_unchained(); + } + + function __DataServicePausable_init_unchained() internal {} + + function _setPauseGuardian(address _pauseGuardian, bool _allowed) internal whenNotPaused { + pauseGuardians[_pauseGuardian] = _allowed; + emit PauseGuardianSet(_pauseGuardian, _allowed); + } +} diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index ea7ef45c8..4a95e2f4c 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -4,17 +4,17 @@ pragma solidity 0.8.26; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; -import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { MulticallUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; -import { GraphPaymentsStorageV1Storage } from "./GraphPaymentsStorage.sol"; -contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Storage, IGraphPayments { +contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, IGraphPayments { using TokenUtils for IGraphToken; using PPMMath for uint256; - + uint256 public immutable PROTOCOL_PAYMENT_CUT; event GraphPaymentsCollected( address indexed sender, address indexed receiver, @@ -25,16 +25,13 @@ contract GraphPayments is Multicall, GraphDirectory, GraphPaymentsStorageV1Stora uint256 tokensProtocol ); - // -- Events -- - - // -- Modifier -- - - // -- Parameters -- - - // -- Constructor -- - constructor(address controller, uint256 protocolPaymentCut) GraphDirectory(controller) { PROTOCOL_PAYMENT_CUT = protocolPaymentCut; + _disableInitializers(); + } + + function initialize() external initializer { + __Multicall_init(); } // collect funds from a sender, pay cuts and forward the rest to the receiver diff --git a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol b/packages/horizon/contracts/payments/GraphPaymentsStorage.sol deleted file mode 100644 index 409b42a80..000000000 --- a/packages/horizon/contracts/payments/GraphPaymentsStorage.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; - -contract GraphPaymentsStorageV1Storage { - // The graph protocol payment cut - uint256 public immutable PROTOCOL_PAYMENT_CUT; -} diff --git a/packages/horizon/package.json b/packages/horizon/package.json index 1118b1b19..e6001d96c 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -21,6 +21,7 @@ "@nomicfoundation/hardhat-toolbox": "^4.0.0", "@nomicfoundation/hardhat-verify": "^2.0.0", "@openzeppelin/contracts": "^5.0.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2", "@typechain/ethers-v6": "^0.5.0", "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", diff --git a/packages/horizon/remappings.txt b/packages/horizon/remappings.txt index 758c61447..aa8b4e6b7 100644 --- a/packages/horizon/remappings.txt +++ b/packages/horizon/remappings.txt @@ -4,3 +4,4 @@ ds-test/=lib/forge-std/lib/ds-test/src/ eth-gas-reporter/=node_modules/eth-gas-reporter/ hardhat/=node_modules/hardhat/ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ +@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/ diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 55c8c6622..178659120 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -12,7 +12,8 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { Attestation } from "./libraries/Attestation.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; import { AttestationManager } from "./utilities/AttestationManager.sol"; @@ -40,7 +41,14 @@ import { AttestationManager } from "./utilities/AttestationManager.sol"; * Disputes can only be accepted, rejected or drawn by the arbitrator role that can be delegated * to a EOA or DAO. */ -contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeManagerV1Storage, IDisputeManager { +contract DisputeManager is + Initializable, + OwnableUpgradeable, + GraphDirectory, + AttestationManager, + DisputeManagerV1Storage, + IDisputeManager +{ using TokenUtils for IGraphToken; using PPMMath for uint256; @@ -69,26 +77,28 @@ contract DisputeManager is Ownable, GraphDirectory, AttestationManager, DisputeM _; } - // -- Functions -- + constructor(address controller) GraphDirectory(controller) { + _disableInitializers(); + } /** * @dev Initialize this contract. - * @param controller Address of Graph Controller contract * @param arbitrator Arbitrator role * @param disputePeriod Dispute period in seconds * @param minimumDeposit Minimum deposit required to create a Dispute * @param fishermanRewardCut_ Percent of slashed funds for fisherman (ppm) * @param maxSlashingCut_ Maximum percentage of indexer stake that can be slashed (ppm) */ - constructor( - address controller, + function initialize( address arbitrator, uint64 disputePeriod, uint256 minimumDeposit, uint32 fishermanRewardCut_, uint32 maxSlashingCut_ - ) Ownable(msg.sender) GraphDirectory(controller) { - // Settings + ) external initializer { + __Ownable_init(msg.sender); + __AttestationManager_init(); + _setArbitrator(arbitrator); _setDisputePeriod(disputePeriod); _setMinimumDeposit(minimumDeposit); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 5a5598b47..97fa8e119 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -6,8 +6,9 @@ import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPC import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { DataServicePausable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServicePausable.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { DataServicePausableUpgradeable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol"; import { DataService } from "@graphprotocol/horizon/contracts/data-service/DataService.sol"; import { DataServiceRescuable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServiceRescuable.sol"; import { DataServiceFees } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServiceFees.sol"; @@ -21,9 +22,10 @@ import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; // TODO: contract needs to be upgradeable contract SubgraphService is - Ownable, + Initializable, + OwnableUpgradeable, DataService, - DataServicePausable, + DataServicePausableUpgradeable, DataServiceRescuable, DataServiceFees, Directory, @@ -53,15 +55,16 @@ contract SubgraphService is address graphController, address disputeManager, address tapVerifier, - address curation, - uint256 minimumProvisionTokens, - uint32 maximumDelegationRatio - ) - Ownable(msg.sender) - DataService(graphController) - Directory(address(this), tapVerifier, disputeManager, curation) - AllocationManager("SubgraphService", "1.0") - { + address curation + ) DataService(graphController) Directory(address(this), tapVerifier, disputeManager, curation) { + _disableInitializers(); + } + + function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external initializer { + __Ownable_init(msg.sender); + __DataServicePausable_init(); + __AllocationManager_init("SubgraphService", "1.0"); + _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); _setDelegationRatioRange(type(uint32).min, maximumDelegationRatio); } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index ee0f5f2eb..3512336e3 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -8,13 +8,13 @@ import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; +import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; -abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManagerV1Storage { +abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, AllocationManagerV1Storage { using ProvisionTracker for mapping(address => uint256); using Allocation for mapping(address => Allocation.State); using Allocation for Allocation.State; @@ -81,7 +81,12 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager error AllocationManagerAllocationSameSize(address allocationId, uint256 tokens); error AllocationManagerInvalidZeroPOI(); - constructor(string memory name, string memory version) EIP712(name, version) {} + function __AllocationManager_init(string memory name, string memory version) internal { + __EIP712_init(name, version); + __AllocationManager_init_unchained(name, version); + } + + function __AllocationManager_init_unchained(string memory name, string memory version) internal {} function setRewardsDestination(address rewardsDestination) external { _setRewardsDestination(msg.sender, rewardsDestination); @@ -284,7 +289,6 @@ abstract contract AllocationManager is EIP712, GraphDirectory, AllocationManager } function _encodeAllocationProof(address _indexer, address _allocationId) internal view returns (bytes32) { - return - EIP712._hashTypedDataV4(keccak256(abi.encode(EIP712_ALLOCATION_PROOF_TYPEHASH, _indexer, _allocationId))); + return _hashTypedDataV4(keccak256(abi.encode(EIP712_ALLOCATION_PROOF_TYPEHASH, _indexer, _allocationId))); } } diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index b68a6804d..535774c1a 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -16,8 +16,11 @@ abstract contract AttestationManager is AttestationManagerV1Storage { bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); bytes32 private constant DOMAIN_SALT = 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; - constructor() { - // EIP-712 domain separator + function __AttestationManager_init() internal { + __AttestationManager_init_unchained(); + } + + function __AttestationManager_init_unchained() internal { _domainSeparator = keccak256( abi.encode( DOMAIN_TYPE_HASH, diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index 6e963c603..b591a4d41 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -22,6 +22,7 @@ "@nomicfoundation/hardhat-toolbox": "^4.0.0", "@nomicfoundation/hardhat-verify": "^2.0.0", "@openzeppelin/contracts": "^5.0.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2", "@typechain/ethers-v6": "^0.5.0", "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", diff --git a/packages/subgraph-service/remappings.txt b/packages/subgraph-service/remappings.txt index d9bed44ec..485676dc2 100644 --- a/packages/subgraph-service/remappings.txt +++ b/packages/subgraph-service/remappings.txt @@ -4,3 +4,5 @@ forge-std/=lib/forge-std/src/ ds-test/=lib/forge-std/lib/ds-test/src/ eth-gas-reporter/=node_modules/eth-gas-reporter/ hardhat/=node_modules/hardhat/ +@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/ +@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol index b13fc8109..f11f0a051 100644 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -24,21 +24,21 @@ contract DisputeManagerTest is Test { address governor; address arbitrator; - + uint256 indexerPrivateKey; address indexer; - + uint256 fishermanPrivateKey; address fisherman; - + uint256 allocationIDPrivateKey; address allocationID; - + uint64 disputePeriod = 300; // 5 minutes uint256 minimumDeposit = 100 ether; // 100 GRT uint32 fishermanRewardPercentage = 100000; // 10% uint32 maxSlashingPercentage = 500000; // 50% - + Controller controller; MockGRTToken graphToken; SubgraphService subgraphService; @@ -53,17 +53,17 @@ contract DisputeManagerTest is Test { indexerPrivateKey = 0xB1; indexer = vm.addr(indexerPrivateKey); - + fishermanPrivateKey = 0xC1; fisherman = vm.addr(fishermanPrivateKey); - + allocationIDPrivateKey = 0xD1; allocationID = vm.addr(allocationIDPrivateKey); graphToken = new MockGRTToken(); staking = new MockHorizonStaking(address(graphToken)); rewardsManager = new MockRewardsManager(); - + address tapVerifier = address(0xE3); address curation = address(0xE4); @@ -74,8 +74,8 @@ contract DisputeManagerTest is Test { controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); vm.stopPrank(); - disputeManager = new DisputeManager( - address(controller), + disputeManager = new DisputeManager(address(controller)); + disputeManager.initialize( arbitrator, disputePeriod, minimumDeposit, @@ -83,14 +83,8 @@ contract DisputeManagerTest is Test { maxSlashingPercentage ); - subgraphService = new SubgraphService( - address(controller), - address(disputeManager), - tapVerifier, - curation, - 1000 ether, - 16 - ); + subgraphService = new SubgraphService(address(controller), address(disputeManager), tapVerifier, curation); + subgraphService.initialize(1000 ether, 16); disputeManager.setSubgraphService(address(subgraphService)); } @@ -105,17 +99,9 @@ contract DisputeManagerTest is Test { bytes32 digest = subgraphService.encodeAllocationProof(indexer, _allocationID); (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - subgraphService.register( - indexer, - abi.encode("url", "geoHash") - ); + subgraphService.register(indexer, abi.encode("url", "geoHash")); - bytes memory data = abi.encode( - subgraphDeployment, - tokens, - _allocationID, - abi.encodePacked(r, s, v) - ); + bytes memory data = abi.encode(subgraphDeployment, tokens, _allocationID, abi.encodePacked(r, s, v)); subgraphService.startService(indexer, data); vm.stopPrank(); } @@ -136,7 +122,7 @@ contract DisputeManagerTest is Test { subgraphDeploymentId: keccak256(abi.encodePacked("Subgraph Deployment ID")) }); bytes memory attestationData = createAtestationData(receipt, allocationIDPrivateKey); - + vm.startPrank(fisherman); graphToken.mint(fisherman, tokens); graphToken.approve(address(disputeManager), tokens); @@ -169,10 +155,13 @@ contract DisputeManagerTest is Test { return (_attestationData1, _attestationData2); } - function createAtestationData(Attestation.Receipt memory receipt, uint256 signer) private view returns (bytes memory attestationData) { + function createAtestationData( + Attestation.Receipt memory receipt, + uint256 signer + ) private view returns (bytes memory attestationData) { bytes32 digest = disputeManager.encodeReceipt(receipt); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); - + return abi.encodePacked(receipt.requestCID, receipt.responseCID, receipt.subgraphDeploymentId, r, s, v); } @@ -201,17 +190,18 @@ contract DisputeManagerTest is Test { bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - (bytes memory attestationData1, bytes memory attestationData2) = - createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); + (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); assertTrue(disputeManager.isDisputeCreated(disputeID1), "Dispute 1 should be created."); assertTrue(disputeManager.isDisputeCreated(disputeID2), "Dispute 2 should be created."); } @@ -219,7 +209,7 @@ contract DisputeManagerTest is Test { function test_RevertWhen_DisputeAlreadyCreated() public { createProvisionAndAllocate(allocationID, 10000 ether); bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); - + // Create another dispute with different fisherman address otherFisherman = address(0x5); uint256 tokens = 200 ether; @@ -236,7 +226,11 @@ contract DisputeManagerTest is Test { // minimum deposit is 100 ether vm.startPrank(fisherman); graphToken.mint(fisherman, 50 ether); - bytes memory expectedError = abi.encodeWithSignature("DisputeManagerInsufficientDeposit(uint256,uint256)", 50 ether, 100 ether); + bytes memory expectedError = abi.encodeWithSignature( + "DisputeManagerInsufficientDeposit(uint256,uint256)", + 50 ether, + 100 ether + ); vm.expectRevert(expectedError); disputeManager.createIndexingDispute(allocationID, 50 ether); vm.stopPrank(); @@ -259,23 +253,22 @@ contract DisputeManagerTest is Test { bytes32 responseCID = keccak256(abi.encodePacked("Response CID")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - (bytes memory attestationData1, bytes memory attestationData2) = - createConflictingAttestations( - responseCID, - subgraphDeploymentId, - responseCID, - subgraphDeploymentId - ); + (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( + responseCID, + subgraphDeploymentId, + responseCID, + subgraphDeploymentId + ); vm.prank(fisherman); bytes memory expectedError = abi.encodeWithSignature( "DisputeManagerNonConflictingAttestations(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32)", - requestCID, - responseCID, - subgraphDeploymentId, - requestCID, - responseCID, + requestCID, + responseCID, + subgraphDeploymentId, + requestCID, + responseCID, subgraphDeploymentId ); vm.expectRevert(expectedError); @@ -289,22 +282,21 @@ contract DisputeManagerTest is Test { bytes32 subgraphDeploymentId1 = keccak256(abi.encodePacked("Subgraph Deployment ID 1")); bytes32 subgraphDeploymentId2 = keccak256(abi.encodePacked("Subgraph Deployment ID 2")); - (bytes memory attestationData1, bytes memory attestationData2) = - createConflictingAttestations( - responseCID1, - subgraphDeploymentId1, - responseCID2, - subgraphDeploymentId2 - ); + (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( + responseCID1, + subgraphDeploymentId1, + responseCID2, + subgraphDeploymentId2 + ); vm.prank(fisherman); bytes memory expectedError = abi.encodeWithSignature( "DisputeManagerNonConflictingAttestations(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32)", - requestCID, - responseCID1, - subgraphDeploymentId1, - requestCID, - responseCID2, + requestCID, + responseCID1, + subgraphDeploymentId1, + requestCID, + responseCID2, subgraphDeploymentId2 ); vm.expectRevert(expectedError); @@ -342,18 +334,19 @@ contract DisputeManagerTest is Test { bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - (bytes memory attestationData1, bytes memory attestationData2) = - createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); + (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); - + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); + vm.prank(arbitrator); disputeManager.acceptDispute(disputeID1, 5000 ether); @@ -411,21 +404,22 @@ contract DisputeManagerTest is Test { bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - (bytes memory attestationData1, bytes memory attestationData2) = - createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); + (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); // skip to end of dispute period skip(disputePeriod + 1); - + vm.prank(fisherman); disputeManager.cancelDispute(disputeID1); @@ -466,18 +460,19 @@ contract DisputeManagerTest is Test { bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - (bytes memory attestationData1, bytes memory attestationData2) = - createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); + (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); - + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); + vm.prank(arbitrator); disputeManager.drawDispute(disputeID1); From 75c5b36a1d7b4bb6d95d5dbca76a10a10b7c0ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 28 May 2024 14:56:26 -0300 Subject: [PATCH 082/277] chore: complete some interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/GraphDirectory.sol | 6 +++--- .../extensions/DataServiceFees.sol | 2 +- .../extensions/DataServicePausable.sol | 4 ++-- .../DataServicePausableUpgradeable.sol | 6 ++++-- .../contracts/interfaces/IGraphPayments.sol | 11 +++++++++++ .../contracts/interfaces/IPaymentsEscrow.sol | 5 +++++ .../internal/IHorizonStakingMain.sol | 18 ++++++++++++++---- .../contracts/payments/GraphPayments.sol | 9 --------- .../contracts/payments/PaymentsEscrow.sol | 18 +++++++++--------- .../contracts/staking/HorizonStaking.sol | 16 ++++++++-------- .../contracts/staking/HorizonStakingBase.sol | 2 +- .../staking/HorizonStakingStorage.sol | 4 ++-- .../contracts/DisputeManager.sol | 12 ++++++------ .../contracts/SubgraphService.sol | 10 +++++----- .../contracts/interfaces/IDisputeManager.sol | 14 ++++++++++---- .../contracts/interfaces/ISubgraphService.sol | 3 ++- .../contracts/utilities/AllocationManager.sol | 2 +- yarn.lock | 11 +++++++++++ 18 files changed, 95 insertions(+), 58 deletions(-) diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index decb73e21..a59200982 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -43,11 +43,11 @@ abstract contract GraphDirectory { ICuration private immutable GRAPH_CURATION; event GraphDirectoryInitialized( - IGraphToken graphToken, - IHorizonStaking graphStaking, + IGraphToken indexed graphToken, + IHorizonStaking indexed graphStaking, IGraphPayments graphPayments, IPaymentsEscrow graphEscrow, - IController graphController, + IController indexed graphController, IEpochManager graphEpochManager, IRewardsManager graphRewardsManager, ITokenGateway graphTokenGateway, diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 0e418503d..b8602eb2a 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -13,7 +13,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat using ProvisionTracker for mapping(address => uint256); using LinkedList for LinkedList.List; - function releaseStake(uint256 n) external virtual override { + function releaseStake(uint256 n) external virtual { _releaseStake(msg.sender, n); } diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index 43a09f3f2..df8c1c402 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -14,11 +14,11 @@ abstract contract DataServicePausable is Pausable, DataService, IDataServicePaus _; } - function pause() public onlyPauseGuardian whenNotPaused { + function pause() external onlyPauseGuardian whenNotPaused { _pause(); } - function unpause() public onlyPauseGuardian whenPaused { + function unpause() external onlyPauseGuardian whenPaused { _unpause(); } diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol index ad60c4c9f..a57087e0e 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol @@ -14,19 +14,21 @@ abstract contract DataServicePausableUpgradeable is PausableUpgradeable, DataSer _; } - function pause() public onlyPauseGuardian whenNotPaused { + function pause() external onlyPauseGuardian whenNotPaused { _pause(); } - function unpause() public onlyPauseGuardian whenPaused { + function unpause() external onlyPauseGuardian whenPaused { _unpause(); } + // solhint-disable-next-line func-name-mixedcase function __DataServicePausable_init() internal { __Pausable_init_unchained(); __DataServicePausable_init_unchained(); } + // solhint-disable-next-line func-name-mixedcase function __DataServicePausable_init_unchained() internal {} function _setPauseGuardian(address _pauseGuardian, bool _allowed) internal whenNotPaused { diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 8c52b18be..c3889222f 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -9,10 +9,21 @@ interface IGraphPayments { IndexingRewards } + event GraphPaymentsCollected( + address indexed sender, + address indexed receiver, + address indexed dataService, + uint256 tokensReceiver, + uint256 tokensDelegationPool, + uint256 tokensDataService, + uint256 tokensProtocol + ); // -- Errors -- error GraphPaymentsInsufficientTokens(uint256 available, uint256 required); + function initialize() external; + // collect funds from a sender, pay cuts and forward the rest to the receiver function collect( PaymentTypes paymentType, diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 12b64cb87..7b39d77df 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -46,6 +46,11 @@ interface IPaymentsEscrow { error PaymentsEscrowInsufficientAllowance(uint256 current, uint256 required); error PaymentsEscrowInconsistentAllowance(uint256 current, uint256 required); error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); + + function approveCollector(address dataService, uint256 thawingPeriod) external; + function thawCollector(address dataService) external; + function cancelThawCollector(address dataService) external; + function revokeCollector(address dataService) external; // Deposit funds into the escrow for a receiver function deposit(address receiver, uint256 tokens) external; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index d11d958b8..33e6ea8c4 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -72,7 +72,7 @@ interface IHorizonStakingMain is IHorizonStakingBase { event DelegationSlashingEnabled(bool enabled); - event AllowedLockedVerifierSet(address verifier, bool allowed); + event AllowedLockedVerifierSet(address indexed verifier, bool allowed); event TokensToDelegationPoolAdded(address indexed serviceProvider, address indexed verifier, uint256 tokens); @@ -96,12 +96,17 @@ interface IHorizonStakingMain is IHorizonStakingBase { /** * @dev Emitted when an operator is allowed or denied by a service provider for a particular data service */ - event OperatorSet(address indexed serviceProvider, address indexed operator, address verifier, bool allowed); + event OperatorSet( + address indexed serviceProvider, + address indexed operator, + address indexed verifier, + bool allowed + ); event DelegationFeeCutSet( address indexed serviceProvider, address indexed verifier, - IGraphPayments.PaymentTypes paymentType, + IGraphPayments.PaymentTypes indexed paymentType, uint256 feeCut ); @@ -119,10 +124,10 @@ interface IHorizonStakingMain is IHorizonStakingBase { error HorizonStakingVerifierNotAllowed(address verifier); error HorizonStakingVerifierTokensTooHigh(uint256 tokensVerifier, uint256 maxVerifierTokens); error HorizonStakingNotEnoughDelegation(uint256 tokensAvailable, uint256 tokensRequired); - error HorizonStakingStillThawing(uint256 until); error HorizonStakingInvalidZeroShares(); error HorizonStakingInvalidSharesAmount(uint256 sharesAvailable, uint256 sharesRequired); error HorizonStakingCallerIsServiceProvider(); + error HorizonStakingStillThawing(uint256 until); error HorizonStakingCannotFulfillThawRequest(); // deposit stake @@ -261,4 +266,9 @@ interface IHorizonStakingMain is IHorizonStakingBase { * @param verifier The verifier / data service on which they're claiming to act */ function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); + + function clearThawingPeriod() external; + function delegate(address serviceProvider, uint256 tokens) external; + function undelegate(address serviceProvider, uint256 shares) external; + function withdrawDelegated(address serviceProvider, address newServiceProvider) external; } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 4a95e2f4c..274337af0 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -15,15 +15,6 @@ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, I using TokenUtils for IGraphToken; using PPMMath for uint256; uint256 public immutable PROTOCOL_PAYMENT_CUT; - event GraphPaymentsCollected( - address indexed sender, - address indexed receiver, - address indexed dataService, - uint256 tokensReceiver, - uint256 tokensDelegationPool, - uint256 tokensDataService, - uint256 tokensProtocol - ); constructor(address controller, uint256 protocolPaymentCut) GraphDirectory(controller) { PROTOCOL_PAYMENT_CUT = protocolPaymentCut; diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 19274123a..5b62863ec 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -52,7 +52,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // approve a data service to collect funds - function approveCollector(address dataService, uint256 tokens) external { + function approveCollector(address dataService, uint256 tokens) external override { Collector storage collector = authorizedCollectors[msg.sender][dataService]; require(tokens > collector.allowance, PaymentsEscrowInconsistentAllowance(collector.allowance, tokens)); @@ -62,7 +62,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // thaw a data service's collector authorization - function thawCollector(address dataService) external { + function thawCollector(address dataService) external override { authorizedCollectors[msg.sender][dataService].thawEndTimestamp = block.timestamp + REVOKE_COLLECTOR_THAWING_PERIOD; @@ -70,7 +70,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // cancel thawing a data service's collector authorization - function cancelThawCollector(address dataService) external { + function cancelThawCollector(address dataService) external override { require(authorizedCollectors[msg.sender][dataService].thawEndTimestamp != 0, PaymentsEscrowNotThawing()); authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; @@ -78,7 +78,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // revoke authorized collector - function revokeCollector(address dataService) external { + function revokeCollector(address dataService) external override { Collector storage collector = authorizedCollectors[msg.sender][dataService]; require(collector.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); @@ -92,14 +92,14 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // Deposit funds into the escrow for a receiver - function deposit(address receiver, uint256 tokens) external { + function deposit(address receiver, uint256 tokens) external override { escrowAccounts[msg.sender][receiver].balance += tokens; _graphToken().pullTokens(msg.sender, tokens); emit Deposit(msg.sender, receiver, tokens); } // Requests to thaw a specific amount of escrow from a receiver's escrow account - function thaw(address receiver, uint256 tokens) external { + function thaw(address receiver, uint256 tokens) external override { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; if (tokens == 0) { // if amount thawing is zero and requested amount is zero this is an invalid request. @@ -124,7 +124,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // Withdraws all thawed escrow from a receiver's escrow account - function withdraw(address receiver) external { + function withdraw(address receiver) external override { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; require(account.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); require( @@ -150,7 +150,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { uint256 tokens, address dataService, uint256 tokensDataService - ) external { + ) external override { // Check if collector is authorized and has enough funds Collector storage collector = authorizedCollectors[payer][msg.sender]; require(collector.authorized, PaymentsEscrowCollectorNotAuthorized(payer, msg.sender)); @@ -182,7 +182,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { } // Get the balance of a sender-receiver pair - function getBalance(address payer, address receiver) external view returns (uint256) { + function getBalance(address payer, address receiver) external view override returns (uint256) { EscrowAccount storage account = escrowAccounts[payer][receiver]; return account.balance - account.tokensThawing; } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index e72027cbb..4c779bda5 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -320,24 +320,24 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { IGraphPayments.PaymentTypes paymentType, uint256 feeCut ) external override notPaused onlyAuthorized(serviceProvider, verifier) { - delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; + _delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); } // For backwards compatibility, delegates to the subgraph data service // (Note this one doesn't have splippage/rounding protection!) - function delegate(address serviceProvider, uint256 tokens) external notPaused { + function delegate(address serviceProvider, uint256 tokens) external override notPaused { _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); } // For backwards compatibility, undelegates from the subgraph data service - function undelegate(address serviceProvider, uint256 shares) external notPaused { + function undelegate(address serviceProvider, uint256 shares) external override notPaused { _undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); } // For backwards compatibility, withdraws delegated tokens from the subgraph data service - function withdrawDelegated(address serviceProvider, address newServiceProvider) external notPaused { + function withdrawDelegated(address serviceProvider, address newServiceProvider) external override notPaused { _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0, 0); } @@ -396,7 +396,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { tokensToSlash = tokensToSlash - providerTokensSlashed; if (tokensToSlash > 0) { DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); - if (delegationSlashingEnabled) { + if (_delegationSlashingEnabled) { require(pool.tokens >= tokensToSlash, HorizonStakingNotEnoughDelegation(pool.tokens, tokensToSlash)); _graphToken().burnTokens(tokensToSlash); uint256 delegationFractionSlashed = (tokensToSlash * FIXED_POINT_PRECISION) / pool.tokens; @@ -448,18 +448,18 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * GOVERNANCE */ - function setAllowedLockedVerifier(address verifier, bool allowed) external onlyGovernor { + function setAllowedLockedVerifier(address verifier, bool allowed) external override onlyGovernor { _allowedLockedVerifiers[verifier] = allowed; emit AllowedLockedVerifierSet(verifier, allowed); } function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { - delegationSlashingEnabled = enabled; + _delegationSlashingEnabled = enabled; emit DelegationSlashingEnabled(enabled); } // To be called at the end of the transition period, to set the deprecated thawing period to 0 - function clearThawingPeriod() external onlyGovernor { + function clearThawingPeriod() external override onlyGovernor { __DEPRECATED_thawingPeriod = 0; emit ThawingPeriodCleared(); } diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 27b8e10e3..81d4b061e 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -121,7 +121,7 @@ abstract contract HorizonStakingBase is address verifier, IGraphPayments.PaymentTypes paymentType ) external view override returns (uint256) { - return delegationFeeCut[serviceProvider][verifier][paymentType]; + return _delegationFeeCut[serviceProvider][verifier][paymentType]; } // provisioned tokens from delegators that are not being thawed diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 8d147866a..c69bbca51 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -135,7 +135,7 @@ abstract contract HorizonStakingV1Storage { /// (based on stake vs delegated stake proportion). /// The cuts are applied in GraphPayments so apply to all data services that use it. mapping(address serviceProvider => mapping(address verifier => mapping(IGraphPayments.PaymentTypes paymentType => uint256 feeCut))) - public delegationFeeCut; + internal _delegationFeeCut; mapping(bytes32 thawRequestId => IHorizonStakingTypes.ThawRequest thawRequest) internal _thawRequests; @@ -147,7 +147,7 @@ abstract contract HorizonStakingV1Storage { internal _operatorAuth; // governance enables or disables delegation slashing with this flag - bool public delegationSlashingEnabled; + bool internal _delegationSlashingEnabled; // delegation pools for each service provider and verifier mapping(address serviceProvider => mapping(address verifier => IHorizonStakingTypes.DelegationPoolInternal delegationPool)) diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 178659120..e85fb54d7 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -95,7 +95,7 @@ contract DisputeManager is uint256 minimumDeposit, uint32 fishermanRewardCut_, uint32 maxSlashingCut_ - ) external initializer { + ) external override initializer { __Ownable_init(msg.sender); __AttestationManager_init(); @@ -315,7 +315,7 @@ contract DisputeManager is * @notice Update the subgraph service to `_subgraphService` * @param subgraphService The address of the subgraph service contract */ - function setSubgraphService(address subgraphService) external onlyOwner { + function setSubgraphService(address subgraphService) external override onlyOwner { _setSubgraphService(subgraphService); } @@ -327,7 +327,7 @@ contract DisputeManager is * @param receipt Receipt returned by indexer and submitted by fisherman * @return Message hash used to sign the receipt */ - function encodeReceipt(Attestation.Receipt memory receipt) external view returns (bytes32) { + function encodeReceipt(Attestation.Receipt memory receipt) external view override returns (bytes32) { return _encodeReceipt(receipt); } @@ -335,7 +335,7 @@ contract DisputeManager is * @dev Get the verifier cut. * @return Verifier cut in percentage (ppm) */ - function getVerifierCut() external view returns (uint32) { + function getVerifierCut() external view override returns (uint32) { return fishermanRewardCut; } @@ -343,14 +343,14 @@ contract DisputeManager is * @dev Get the dispute period. * @return Dispute period in seconds */ - function getDisputePeriod() external view returns (uint64) { + function getDisputePeriod() external view override returns (uint64) { return disputePeriod; } function areConflictingAttestations( Attestation.State memory attestation1, Attestation.State memory attestation2 - ) external pure returns (bool) { + ) external pure override returns (bool) { return Attestation.areConflicting(attestation1, attestation2); } diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 97fa8e119..29dc8e9e1 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -60,7 +60,7 @@ contract SubgraphService is _disableInitializers(); } - function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external initializer { + function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external override initializer { __Ownable_init(msg.sender); __DataServicePausable_init(); __AllocationManager_init("SubgraphService", "1.0"); @@ -169,11 +169,11 @@ contract SubgraphService is address indexer, address allocationId, bytes32 subgraphDeploymentID - ) external onlyOwner { + ) external override onlyOwner { _migrateLegacyAllocation(indexer, allocationId, subgraphDeploymentID); } - function setPauseGuardian(address pauseGuardian, bool allowed) external onlyOwner { + function setPauseGuardian(address pauseGuardian, bool allowed) external override onlyOwner { _setPauseGuardian(pauseGuardian, allowed); } @@ -193,11 +193,11 @@ contract SubgraphService is ); } - function getLegacyAllocation(address allocationId) external view returns (LegacyAllocation.State memory) { + function getLegacyAllocation(address allocationId) external view override returns (LegacyAllocation.State memory) { return legacyAllocations[allocationId]; } - function encodeAllocationProof(address indexer, address allocationId) external view returns (bytes32) { + function encodeAllocationProof(address indexer, address allocationId) external view override returns (bytes32) { return _encodeAllocationProof(indexer, allocationId); } diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index a72956a29..27bd0418f 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -34,7 +34,7 @@ interface IDisputeManager { } // -- Events -- - event ArbitratorSet(address arbitrator); + event ArbitratorSet(address indexed arbitrator); event DisputePeriodSet(uint64 disputePeriod); event MinimumDepositSet(uint256 minimumDeposit); event MaxSlashingCutSet(uint32 maxSlashingCut); @@ -131,9 +131,13 @@ interface IDisputeManager { bytes32 subgraphDeploymentId2 ); - // -- Attestation -- - - // -- Configuration -- + function initialize( + address arbitrator, + uint64 disputePeriod, + uint256 minimumDeposit, + uint32 fishermanRewardCut, + uint32 maxSlashingCut + ) external; function setDisputePeriod(uint64 disputePeriod) external; @@ -180,4 +184,6 @@ interface IDisputeManager { Attestation.State memory attestation1, Attestation.State memory attestation2 ) external pure returns (bool); + + function setSubgraphService(address subgraphService) external; } diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 3bf6ed711..868e63fca 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -20,7 +20,7 @@ interface ISubgraphService is IDataServiceFees { } event QueryFeesCollected( - address serviceProvider, + address indexed serviceProvider, uint256 tokensCollected, uint256 tokensCurators, uint256 tokensSubgraphService @@ -32,6 +32,7 @@ interface ISubgraphService is IDataServiceFees { error SubgraphServiceIndexerNotRegistered(address indexer); error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); + function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external; function resizeAllocation(address indexer, address allocationId, uint256 tokens) external; function migrateLegacyAllocation(address indexer, address allocationId, bytes32 subgraphDeploymentID) external; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 3512336e3..0e67014dc 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -72,7 +72,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca bytes32 indexed subgraphDeploymentId ); - event RewardsDestinationSet(address indexed indexer, address rewardsDestination); + event RewardsDestinationSet(address indexed indexer, address indexed rewardsDestination); error AllocationManagerInvalidAllocationProof(address signer, address allocationId); error AllocationManagerInvalidAllocationId(); diff --git a/yarn.lock b/yarn.lock index 98c24bbfa..29b385618 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2922,6 +2922,7 @@ __metadata: "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" "@nomicfoundation/hardhat-verify": "npm:^2.0.0" "@openzeppelin/contracts": "npm:^5.0.2" + "@openzeppelin/contracts-upgradeable": "npm:^5.0.2" "@typechain/ethers-v6": "npm:^0.5.0" "@typechain/hardhat": "npm:^9.0.0" "@types/chai": "npm:^4.2.0" @@ -3011,6 +3012,7 @@ __metadata: "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" "@nomicfoundation/hardhat-verify": "npm:^2.0.0" "@openzeppelin/contracts": "npm:^5.0.2" + "@openzeppelin/contracts-upgradeable": "npm:^5.0.2" "@typechain/ethers-v6": "npm:^0.5.0" "@typechain/hardhat": "npm:^9.0.0" "@types/chai": "npm:^4.2.0" @@ -4749,6 +4751,15 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts-upgradeable@npm:^5.0.2": + version: 5.0.2 + resolution: "@openzeppelin/contracts-upgradeable@npm:5.0.2" + peerDependencies: + "@openzeppelin/contracts": 5.0.2 + checksum: 0bd47a4fa0ba8084c1df9573968ff02387bc21514d846b5feb4ad42f90f3ba26bb1e40f17f03e4fa24ffbe473b9ea06c137283297884ab7d5b98d2c112904dc9 + languageName: node + linkType: hard + "@openzeppelin/contracts@npm:^3.3.0-solc-0.7, @openzeppelin/contracts@npm:^3.4.1": version: 3.4.2 resolution: "@openzeppelin/contracts@npm:3.4.2" From a2c8b38f9b5acae10d12b35ca8d09b8c9acda9a8 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Mon, 27 May 2024 19:12:52 -0300 Subject: [PATCH 083/277] fix: slashing horizon delegation --- .../contracts/staking/HorizonStaking.sol | 5 +- .../horizon/test/staking/slash/slash.t.sol | 82 +++++++++++++------ 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 4c779bda5..1317de454 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -363,7 +363,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { ) external override notPaused { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; - require(prov.tokens >= tokens, HorizonStakingInsufficientTokens(prov.tokens, tokens)); + DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); + uint256 availableTokens = prov.tokens + pool.tokens; + require(availableTokens >= tokens, HorizonStakingInsufficientTokens(prov.tokens, tokens)); uint256 tokensToSlash = tokens; uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); @@ -395,7 +397,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { tokensToSlash = tokensToSlash - providerTokensSlashed; if (tokensToSlash > 0) { - DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); if (_delegationSlashingEnabled) { require(pool.tokens >= tokensToSlash, HorizonStakingNotEnoughDelegation(pool.tokens, tokensToSlash)); _graphToken().burnTokens(tokensToSlash); diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 9a0951f23..f455ea041 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -7,11 +7,11 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingSlashTest is HorizonStakingTest { - modifier useDelegationSlashingDisabled() { + modifier useDelegationSlashing(bool enabled) { address msgSender; (, msgSender,) = vm.readCallers(); vm.startPrank(users.governor); - staking.setDelegationSlashingEnabled(false); + staking.setDelegationSlashingEnabled(enabled); vm.startPrank(msgSender); _; } @@ -41,33 +41,63 @@ contract HorizonStakingSlashTest is HorizonStakingTest { assertEq(verifierTokens, verifierCutAmount); } - // TODO: Should be re-enabled when slashin is fixed to count for delegated tokens - // function testSlash_DelegationDisabled_SlashingOverProvisionTokens( - // uint256 amount, - // uint256 slashAmount, - // uint256 verifierCutAmount, - // uint256 delegationAmount - // ) public useIndexer useProvision(amount, 100000, 0) useDelegationSlashingDisabled { - // vm.assume(slashAmount > amount); - // vm.assume(delegationAmount > 0); - // uint32 delegationRatio = 5; - - // vm.stopPrank(); - // vm.startPrank(users.delegator); - // _delegate(delegationAmount); - - // vm.startPrank(subgraphDataServiceAddress); - // _slash(slashAmount, verifierCutAmount); + function testSlash_DelegationDisabled_SlashingOverProvisionTokens( + uint256 amount, + uint256 slashAmount, + uint256 verifierCutAmount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(false) { + // TODO: changePrank? + vm.stopPrank(); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); + verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); + + vm.startPrank(users.delegator); + _delegate(delegationAmount); + + vm.startPrank(subgraphDataServiceAddress); + _slash(slashAmount, verifierCutAmount); + + uint256 provisionProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionProviderTokens, 0 ether); + + uint256 verifierTokens = token.balanceOf(address(subgraphDataServiceAddress)); + assertEq(verifierTokens, verifierCutAmount); + + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + // No slashing occurred for delegation + assertEq(delegatedTokens, delegationAmount); + } + + function testSlash_DelegationEnabled_SlashingOverProvisionTokens( + uint256 amount, + uint256 slashAmount, + uint256 verifierCutAmount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(true) { + // TODO: changePrank? + vm.stopPrank(); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); + verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); + + vm.startPrank(users.delegator); + _delegate(delegationAmount); + + vm.startPrank(subgraphDataServiceAddress); + _slash(slashAmount, verifierCutAmount); - // uint256 provisionProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - // assertEq(provisionProviderTokens, 0 ether); + uint256 provisionProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionProviderTokens, 0 ether); - // uint256 verifierTokens = token.balanceOf(address(subgraphDataServiceAddress)); - // assertEq(verifierTokens, verifierCutAmount); + uint256 verifierTokens = token.balanceOf(address(subgraphDataServiceAddress)); + assertEq(verifierTokens, verifierCutAmount); - // uint256 delegatedTokens = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, delegationRatio); - // assertEq(delegatedTokens, delegationAmount); - // } + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + uint256 slashedDelegation = slashAmount - amount; + assertEq(delegatedTokens, delegationAmount - slashedDelegation); + } function testSlash_RevertWhen_NoProvision( uint256 amount, From 7bea04735ff7cd06e90287ea0a2bb35dbda20d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 28 May 2024 17:52:36 -0300 Subject: [PATCH 084/277] docs: add natspec to horizon staking base contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../internal/IHorizonStakingBase.sol | 172 ++++++++++----- .../internal/IHorizonStakingExtension.sol | 9 + .../internal/IHorizonStakingMain.sol | 23 ++ .../internal/IHorizonStakingTypes.sol | 47 ++-- .../contracts/staking/HorizonStaking.sol | 10 +- .../contracts/staking/HorizonStakingBase.sol | 201 +++++++++++------- .../staking/HorizonStakingExtension.sol | 13 +- .../horizon/test/staking/HorizonStaking.t.sol | 2 +- 8 files changed, 323 insertions(+), 154 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index c8dea3da6..563ba258f 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -7,91 +7,165 @@ import { IGraphPayments } from "../IGraphPayments.sol"; import { LinkedList } from "../../libraries/LinkedList.sol"; +/** + * @title Interface for the {HorizonStakingBase} contract. + * @dev Provides getters for {HorizonStaking} and {HorizonStakingExtension} storage variables. + * + * Most functions operate over {HorizonStaking} provisions. To uniquely identify a provision + * functions take `serviceProvider` and `verifier` addresses. + */ interface IHorizonStakingBase { /** - * @dev Emitted when `serviceProvider` stakes `tokens` amount. - * @dev TODO(after transition period): move to IHorizonStakingMain + * @notice Emitted when a service provider stakes tokens. + * @dev TODO: After transition period move to IHorizonStakingMain. Temporarily it + * needs to be here since it's emitted by {_stake} which is used by both {HorizonStaking} + * and {HorizonStakingExtension}. + * @param serviceProvider The address of the service provider. + * @param tokens The amount of tokens staked. */ event StakeDeposited(address indexed serviceProvider, uint256 tokens); /** - * @dev Emitted when `delegator` delegated `tokens` to the `serviceProvider`, the delegator - * gets `shares` for the delegation pool proportionally to the tokens staked. - * This event is here for backwards compatibility, the tokens are delegated - * on the subgraph data service provision. - * @dev TODO(after transition period): move to IHorizonStakingMain + * @notice Gets the details of a service provider. + * @param serviceProvider The address of the service provider. */ - event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); - - event ThawRequestCreated( - address indexed serviceProvider, - address indexed verifier, - address indexed owner, - uint256 shares, - uint64 thawingUntil, - bytes32 thawRequestId - ); - event ThawRequestFulfilled(bytes32 indexed thawRequestId, uint256 tokens, uint256 shares, uint64 thawingUntil); - event ThawRequestsFulfilled( - address indexed serviceProvider, - address indexed verifier, - address indexed owner, - uint256 thawRequestsFulfilled, - uint256 tokens - ); - - error HorizonStakingNothingThawing(); - error HorizonStakingTooManyThawRequests(); - - function getStake(address serviceProvider) external view returns (uint256); - - function getDelegatedTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); - - function getTokensAvailable( - address serviceProvider, - address verifier, - uint32 delegationRatio - ) external view returns (uint256); - function getServiceProvider( address serviceProvider ) external view returns (IHorizonStakingTypes.ServiceProvider memory); - function getMaxThawingPeriod() external view returns (uint64); + /** + * @notice Gets the stake of a service provider. + * @param serviceProvider The address of the service provider. + * @return The amount of tokens staked. + */ + function getStake(address serviceProvider) external view returns (uint256); + /** + * @notice Gets the service provider's idle stake which is the stake that is not being + * used for any provision. Note that this only includes service provider's self stake. + * @param serviceProvider The address of the service provider. + * @return The amount of tokens that are idle. + */ + function getIdleStake(address serviceProvider) external view returns (uint256); + + /** + * @notice Gets the details of delegation pool. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @return The delegation pool details. + */ function getDelegationPool( address serviceProvider, address verifier ) external view returns (IHorizonStakingTypes.DelegationPool memory); + /** + * @notice Gets the details of a delegation. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @param delegator The address of the delegator. + * @return The delegation details. + */ function getDelegation( - address delegator, address serviceProvider, - address verifier + address verifier, + address delegator ) external view returns (IHorizonStakingTypes.Delegation memory); - function getThawRequest(bytes32 thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory); + /** + * @notice Gets the delegation fee cut for a payment type. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @param paymentType The payment type as defined by {IGraphPayments.PaymentTypes}. + * @return The delegation fee cut in PPM. + */ + function getDelegationFeeCut( + address serviceProvider, + address verifier, + IGraphPayments.PaymentTypes paymentType + ) external view returns (uint256); + /** + * @notice Gets the details of a provision. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @return The provision details. + */ function getProvision( address serviceProvider, address verifier ) external view returns (IHorizonStakingTypes.Provision memory); - function getDelegationFeeCut( + /** + * @notice Gets the tokens available in a provision. + * Tokens available are the tokens in a provision that are not thawing. Includes service + * provider's and delegator's stake. + * + * Allows specifying a `delegationRatio` which caps the amount of delegated tokens that are + * considered available. + * + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @param delegationRatio The delegation ratio. + * @return The amount of tokens available. + */ + function getTokensAvailable( address serviceProvider, address verifier, - IGraphPayments.PaymentTypes paymentType + uint32 delegationRatio ) external view returns (uint256); - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) external view returns (uint256 tokens); - + /** + * @notice Gets the service provider's tokens available in a provision. + * @dev Calculated as the tokens available minus the tokens thawing. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @return The amount of tokens available. + */ function getProviderTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); + /** + * @notice Gets the delegator's tokens available in a provision. + * @dev Calculated as the tokens available minus the tokens thawing. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @return The amount of tokens available. + */ + function getDelegatedTokensAvailable(address serviceProvider, address verifier) external view returns (uint256); + + /** + * @notice Gets a thaw request. + * @param thawRequestId The id of the thaw request. + * @return The thaw request details. + */ + function getThawRequest(bytes32 thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory); + + /** + * @notice Gets the metadata of a thaw request list. + * Service provider and delegators each have their own thaw request list per provision. + * Metadata includes the head and tail of the list, plus the total number of thaw requests. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @param owner The owner of the thaw requests. Use either the service provider or delegator address. + * @return The thaw requests list metadata. + */ function getThawRequestList( address serviceProvider, address verifier, address owner ) external view returns (LinkedList.List memory); + + /** + * @notice Gets the amount of thawed tokens for a given provision. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + * @param owner The owner of the thaw requests. Use either the service provider or delegator address. + * @return The amount of thawed tokens. + */ + function getThawedTokens(address serviceProvider, address verifier, address owner) external view returns (uint256); + + /** + * @notice Gets the maximum allowed thawing period for a provision. + */ + function getMaxThawingPeriod() external view returns (uint64); } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index d09bbc3c3..4d7518ec4 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -40,6 +40,15 @@ interface IHorizonStakingExtension { Closed } + /** + * @notice Emitted when a delegator delegates through the Graph Token Gateway using the transfer tools. + * @dev TODO(after transfer tools): delete + * @param serviceProvider The address of the service provider. + * @param delegator The address of the delegator. + * @param tokens The amount of tokens delegated. + */ + event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); + /** * @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`. * An amount of `tokens` get unallocated from `subgraphDeploymentID`. diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 33e6ea8c4..cd53cb613 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -6,6 +6,23 @@ import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; interface IHorizonStakingMain is IHorizonStakingBase { + event ThawRequestCreated( + address indexed serviceProvider, + address indexed verifier, + address indexed owner, + uint256 shares, + uint64 thawingUntil, + bytes32 thawRequestId + ); + event ThawRequestFulfilled(bytes32 indexed thawRequestId, uint256 tokens, uint256 shares, uint64 thawingUntil); + event ThawRequestsFulfilled( + address indexed serviceProvider, + address indexed verifier, + address indexed owner, + uint256 thawRequestsFulfilled, + uint256 tokens + ); + /** * @dev Emitted when `serviceProvider` withdraws `tokens` amount. */ @@ -130,6 +147,9 @@ interface IHorizonStakingMain is IHorizonStakingBase { error HorizonStakingStillThawing(uint256 until); error HorizonStakingCannotFulfillThawRequest(); + error HorizonStakingNothingThawing(); + error HorizonStakingTooManyThawRequests(); + // deposit stake function stake(uint256 tokens) external; @@ -268,7 +288,10 @@ interface IHorizonStakingMain is IHorizonStakingBase { function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); function clearThawingPeriod() external; + function delegate(address serviceProvider, uint256 tokens) external; + function undelegate(address serviceProvider, uint256 shares) external; + function withdrawDelegated(address serviceProvider, address newServiceProvider) external; } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index 13c64d37d..0b59e0b8c 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.26; // TODO: create custom var-name-mixedcase -/* solhint-disable var-name-mixedcase */ interface IHorizonStakingTypes { struct Provision { @@ -31,27 +30,45 @@ interface IHorizonStakingTypes { uint256 tokensProvisioned; } - struct DelegationPoolInternal { - uint32 __DEPRECATED_cooldownBlocks; // solhint-disable-line var-name-mixedcase - uint32 __DEPRECATED_indexingRewardCut; // in PPM - uint32 __DEPRECATED_queryFeeCut; // in PPM - uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated + // the new "Indexer" struct + struct ServiceProviderInternal { + // Tokens on the Service Provider stake (staked by the provider) + uint256 tokensStaked; + // Tokens used in allocations + uint256 __DEPRECATED_tokensAllocated; // solhint-disable-line graph/leading-underscore + // Tokens locked for withdrawal subject to thawing period + uint256 __DEPRECATED_tokensLocked; + // Block when locked tokens can be withdrawn + uint256 __DEPRECATED_tokensLockedUntil; + // tokens used in a provision + uint256 tokensProvisioned; + } + + struct DelegationPool { uint256 tokens; // Total tokens as pool reserves uint256 shares; // Total shares minted in the pool - mapping(address => Delegation) delegators; // Mapping of delegator => Delegation uint256 tokensThawing; // Tokens thawing in the pool uint256 sharesThawing; // Shares representing the thawing tokens } - struct DelegationPool { + struct DelegationPoolInternal { + uint32 __DEPRECATED_cooldownBlocks; + uint32 __DEPRECATED_indexingRewardCut; // in PPM + uint32 __DEPRECATED_queryFeeCut; // in PPM + uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated uint256 tokens; // Total tokens as pool reserves uint256 shares; // Total shares minted in the pool + mapping(address => DelegationInternal) delegators; // Mapping of delegator => Delegation uint256 tokensThawing; // Tokens thawing in the pool uint256 sharesThawing; // Shares representing the thawing tokens } struct Delegation { uint256 shares; // Shares owned by a delegator in the pool + } + + struct DelegationInternal { + uint256 shares; // Shares owned by a delegator in the pool uint256 __DEPRECATED_tokensLocked; // Tokens locked for undelegation uint256 __DEPRECATED_tokensLockedUntil; // Epoch when locked tokens can be withdrawn } @@ -64,18 +81,4 @@ interface IHorizonStakingTypes { // id of the next thaw request in the linked list bytes32 next; } - - // the new "Indexer" struct - struct ServiceProviderInternal { - // Tokens on the Service Provider stake (staked by the provider) - uint256 tokensStaked; - // Tokens used in allocations - uint256 __DEPRECATED_tokensAllocated; // solhint-disable-line graph/leading-underscore - // Tokens locked for withdrawal subject to thawing period - uint256 __DEPRECATED_tokensLocked; - // Block when locked tokens can be withdrawn - uint256 __DEPRECATED_tokensLockedUntil; - // tokens used in a provision - uint256 tokensProvisioned; - } } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 4c779bda5..939200cf4 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -18,8 +18,10 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * @dev This contract is the main Staking contract in The Graph protocol after the Horizon upgrade. * It is designed to be deployed as an upgrade to the L2Staking contract from the legacy contracts * package. - * It uses a HorizonStakingExtension contract to implement the full IHorizonStaking interface through delegatecalls. - * This is due to the contract size limit on Arbitrum (24kB like mainnet). + * @dev It uses a HorizonStakingExtension contract to implement the full IHorizonStaking interface through delegatecalls. + * This is due to the contract size limit on Arbitrum (24kB). The extension contract contains functionality to support + * the legacy staking functions and the transfer tools. Both can be eventually safely removed without affecting + * the main staking contract. */ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { using TokenUtils for IGraphToken; @@ -693,7 +695,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { ); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); - Delegation storage delegation = pool.delegators[msg.sender]; + DelegationInternal storage delegation = pool.delegators[msg.sender]; // Calculate shares to issue uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); @@ -710,7 +712,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { function _undelegate(address _serviceProvider, address _verifier, uint256 _shares) private returns (bytes32) { require(_shares > 0, HorizonStakingInvalidZeroShares()); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); - Delegation storage delegation = pool.delegators[msg.sender]; + DelegationInternal storage delegation = pool.delegators[msg.sender]; require(delegation.shares >= _shares, HorizonStakingInvalidSharesAmount(delegation.shares, _shares)); uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 81d4b061e..e338b9e03 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -15,10 +15,9 @@ import { Managed } from "./utilities/Managed.sol"; import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; /** - * @title L2Staking contract - * @dev This contract is the L2 variant of the Staking contract. It adds a function - * to receive an service provider'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. + * @title HorizonStakingBase contract + * @dev This contract is the base staking contract, to be inherited by HorizonStaking and HorizonStakingExtension. + * It implements all storage getters for both internal and external use. */ abstract contract HorizonStakingBase is Multicall, @@ -44,28 +43,10 @@ abstract contract HorizonStakingBase is revert("RECEIVE_ETH_NOT_ALLOWED"); } - // total staked tokens to the provider - // `ServiceProvider.tokensStaked - function getStake(address serviceProvider) external view override returns (uint256) { - return _serviceProviders[serviceProvider].tokensStaked; - } - - // provisioned tokens that are not being thawed (including provider tokens and delegation) - function getTokensAvailable( - address serviceProvider, - address verifier, - uint32 delegationRatio - ) external view override returns (uint256) { - uint256 providerTokens = _provisions[serviceProvider][verifier].tokens; - uint256 providerThawingTokens = _provisions[serviceProvider][verifier].tokensThawing; - uint256 tokensDelegatedMax = (providerTokens - providerThawingTokens) * (uint256(delegationRatio)); - uint256 tokensDelegatedCapacity = MathUtils.min( - _getDelegatedTokensAvailable(serviceProvider, verifier), - tokensDelegatedMax - ); - return providerTokens - providerThawingTokens + tokensDelegatedCapacity; - } - + /** + * @notice See {IHorizonStakingBase-getServiceProvider}. + * @dev Removes deprecated fields from the return value. + */ function getServiceProvider(address serviceProvider) external view override returns (ServiceProvider memory) { ServiceProvider memory sp; ServiceProviderInternal storage spInternal = _serviceProviders[serviceProvider]; @@ -74,10 +55,24 @@ abstract contract HorizonStakingBase is return sp; } - function getMaxThawingPeriod() external view override returns (uint64) { - return _maxThawingPeriod; + /** + * @notice See {IHorizonStakingBase-getStake}. + */ + function getStake(address serviceProvider) external view override returns (uint256) { + return _serviceProviders[serviceProvider].tokensStaked; + } + + /** + * @notice See {IHorizonStakingBase-getIdleStake}. + */ + function getIdleStake(address serviceProvider) external view override returns (uint256 tokens) { + return _getIdleStake(serviceProvider); } + /** + * @notice See {IHorizonStakingBase-getDelegationPool}. + * @dev Removes deprecated fields from the return value. + */ function getDelegationPool( address serviceProvider, address verifier @@ -91,41 +86,69 @@ abstract contract HorizonStakingBase is return pool; } + /** + * @notice See {IHorizonStakingBase-getDelegation}. + * @dev Removes deprecated fields from the return value. + */ function getDelegation( - address delegator, address serviceProvider, - address verifier + address verifier, + address delegator ) external view override returns (Delegation memory) { + Delegation memory delegation; DelegationPoolInternal storage poolInternal = _getDelegationPool(serviceProvider, verifier); - return poolInternal.delegators[delegator]; - } - - function getThawRequest(bytes32 thawRequestId) external view returns (ThawRequest memory) { - return _thawRequests[thawRequestId]; + delegation.shares = poolInternal.delegators[delegator].shares; + return delegation; } - function getThawRequestList( + /** + * @notice See {IHorizonStakingBase-getDelegationFeeCut}. + */ + function getDelegationFeeCut( address serviceProvider, address verifier, - address owner - ) external view returns (LinkedList.List memory) { - return _thawRequestLists[serviceProvider][verifier][owner]; + IGraphPayments.PaymentTypes paymentType + ) external view override returns (uint256) { + return _delegationFeeCut[serviceProvider][verifier][paymentType]; } + /** + * @notice See {IHorizonStakingBase-getProvision}. + */ function getProvision(address serviceProvider, address verifier) external view override returns (Provision memory) { return _provisions[serviceProvider][verifier]; } - function getDelegationFeeCut( + /** + * @notice See {IHorizonStakingBase-getTokensAvailable}. + */ + function getTokensAvailable( address serviceProvider, address verifier, - IGraphPayments.PaymentTypes paymentType + uint32 delegationRatio ) external view override returns (uint256) { - return _delegationFeeCut[serviceProvider][verifier][paymentType]; + uint256 tokensAvailableProvider = _getProviderTokensAvailable(serviceProvider, verifier); + uint256 tokensAvailableDelegated = _getDelegatedTokensAvailable(serviceProvider, verifier); + + uint256 tokensDelegatedMax = tokensAvailableProvider * (uint256(delegationRatio)); + uint256 tokensDelegatedCapacity = MathUtils.min(tokensAvailableDelegated, tokensDelegatedMax); + + return tokensAvailableProvider + tokensDelegatedCapacity; + } + + /** + * @notice See {IHorizonStakingBase-getProviderTokensAvailable}. + */ + function getProviderTokensAvailable( + address serviceProvider, + address verifier + ) external view override returns (uint256) { + return _getProviderTokensAvailable(serviceProvider, verifier); } - // provisioned tokens from delegators that are not being thawed - // `Provision.delegatedTokens - Provision.delegatedTokensThawing` + /** + * @notice See {IHorizonStakingBase-getDelegatedTokensAvailable}. + */ function getDelegatedTokensAvailable( address serviceProvider, address verifier @@ -133,28 +156,33 @@ abstract contract HorizonStakingBase is return _getDelegatedTokensAvailable(serviceProvider, verifier); } - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) external view override returns (uint256 tokens) { - return _getIdleStake(serviceProvider); + /** + * @notice See {IHorizonStakingBase-getThawRequest}. + */ + function getThawRequest(bytes32 thawRequestId) external view override returns (ThawRequest memory) { + return _thawRequests[thawRequestId]; } - // provisioned tokens from the service provider that are not being thawed - // `Provision.tokens - Provision.tokensThawing` - function getProviderTokensAvailable( + /** + * @notice See {IHorizonStakingBase-getThawRequestList}. + */ + function getThawRequestList( address serviceProvider, - address verifier - ) external view override returns (uint256) { - return _getProviderTokensAvailable(serviceProvider, verifier); + address verifier, + address owner + ) external view override returns (LinkedList.List memory) { + return _thawRequestLists[serviceProvider][verifier][owner]; } /** - * @notice Get the amount of service provider's tokens in a provision that have finished thawing - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned + * @notice See {IHorizonStakingBase-getThawedTokens}. */ - function getThawedTokens(address serviceProvider, address verifier) external view returns (uint256) { - LinkedList.List storage thawRequestList = _thawRequestLists[serviceProvider][verifier][serviceProvider]; + function getThawedTokens( + address serviceProvider, + address verifier, + address owner + ) external view override returns (uint256) { + LinkedList.List storage thawRequestList = _thawRequestLists[serviceProvider][verifier][owner]; if (thawRequestList.count == 0) { return 0; } @@ -175,27 +203,50 @@ abstract contract HorizonStakingBase is return tokens; } + /** + * @notice See {IHorizonStakingBase-getMaxThawingPeriod}. + */ + function getMaxThawingPeriod() external view override returns (uint64) { + return _maxThawingPeriod; + } + /** * @notice Deposit tokens into the service provider stake. - * @dev TODO(after transition period): move to HorizonStaking - * @param _serviceProvider Address of staking party - * @param _tokens Amount of tokens to stake + * @dev TODO: After transition period move to IHorizonStakingMain. Temporarily it + * needs to be here since it's used by both {HorizonStaking} and {HorizonStakingExtension}. + * + * Emits a {StakeDeposited} event. */ function _stake(address _serviceProvider, uint256 _tokens) internal { _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; emit StakeDeposited(_serviceProvider, _tokens); } - function _getNextThawRequest(bytes32 _thawRequestId) internal view returns (bytes32) { - return _thawRequests[_thawRequestId].next; + /** + * @dev Gets the idle stake of a service provider. + * + * Note that the calculation considers tokens that were locked in the legacy staking contract. + * TODO: update the calculation after the transition period. + */ + function _getIdleStake(address _serviceProvider) internal view returns (uint256) { + return + _serviceProviders[_serviceProvider].tokensStaked - + _serviceProviders[_serviceProvider].tokensProvisioned - + _serviceProviders[_serviceProvider].__DEPRECATED_tokensLocked; } + /** + * @dev Gets a delegation pool. + * + * Note that there is a special case if the verifier is the subgraph data service, since + * in that case the pools are stored in the legacy mapping. + */ function _getDelegationPool( address _serviceProvider, address _verifier ) internal view returns (DelegationPoolInternal storage) { IHorizonStakingTypes.DelegationPoolInternal storage pool; - if (_verifier == _serviceProvider) { + if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { pool = _legacyDelegationPools[_serviceProvider]; } else { pool = _delegationPools[_serviceProvider][_verifier]; @@ -203,19 +254,25 @@ abstract contract HorizonStakingBase is return pool; } - function _getIdleStake(address _serviceProvider) internal view returns (uint256 tokens) { - return - _serviceProviders[_serviceProvider].tokensStaked - - _serviceProviders[_serviceProvider].tokensProvisioned - - _serviceProviders[_serviceProvider].__DEPRECATED_tokensLocked; - } - + /** + * @dev See {IHorizonStakingBase-getProviderTokensAvailable}. + */ function _getProviderTokensAvailable(address _serviceProvider, address _verifier) internal view returns (uint256) { return _provisions[_serviceProvider][_verifier].tokens - _provisions[_serviceProvider][_verifier].tokensThawing; } + /** + * @dev See {IHorizonStakingBase-getDelegatedTokensAvailable}. + */ function _getDelegatedTokensAvailable(address _serviceProvider, address _verifier) internal view returns (uint256) { DelegationPoolInternal storage poolInternal = _getDelegationPool(_serviceProvider, _verifier); return poolInternal.tokens - poolInternal.tokensThawing; } + + /** + * @dev Gets the next thaw request in the list. + */ + function _getNextThawRequest(bytes32 _thawRequestId) internal view returns (bytes32) { + return _thawRequests[_thawRequestId].next; + } } diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 284d2dbe6..6265583fe 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -18,14 +18,15 @@ import { PPMMath } from "../libraries/PPMMath.sol"; import { HorizonStakingBase } from "./HorizonStakingBase.sol"; /** - * @title Base Staking contract + * @title Horizon Staking extension contract + * @dev This contract contains: + * - all the legacy staking functionality, required to support the transition period + * - transfer tools support functions + * TODO: once the transition period and the transfer tools are deemed not necessary this contract + * can be removed. * @dev 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 - * and L2Staking on Arbitrum. - * Note that this contract delegates part of its functionality to a StakingExtension contract. - * This is due to the 24kB contract size limit on Ethereum. */ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2StakingBase, IHorizonStakingExtension { using TokenUtils for IGraphToken; @@ -322,7 +323,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki ) internal { // Get the delegation pool of the indexer IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; - IHorizonStakingTypes.Delegation storage delegation = pool.delegators[_delegationData.delegator]; + IHorizonStakingTypes.DelegationInternal storage delegation = pool.delegators[_delegationData.delegator]; // Calculate shares to issue (without applying any delegation tax) uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / pool.tokens); diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index b2c256a2d..961445e8a 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -73,7 +73,7 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { } function _getDelegation() internal view returns (Delegation memory) { - return staking.getDelegation(users.delegator, users.indexer, subgraphDataServiceAddress); + return staking.getDelegation(users.indexer, subgraphDataServiceAddress, users.delegator); } function _undelegate(uint256 shares) internal { From 19591b3d0e75d415e8f17502d098c5d92f59da40 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 28 May 2024 22:40:49 -0300 Subject: [PATCH 085/277] fix: rebase horizon branch --- .../contracts/staking/HorizonStaking.sol | 4 +- .../horizon/test/staking/HorizonStaking.t.sol | 4 +- .../test/staking/provision/deprovision.t.sol | 74 +++++++++---------- .../test/staking/provision/reprovision.t.sol | 41 +++------- packages/horizon/test/staking/thaw/thaw.t.sol | 3 +- 5 files changed, 54 insertions(+), 72 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 1317de454..60b674aab 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -364,8 +364,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); - uint256 availableTokens = prov.tokens + pool.tokens; - require(availableTokens >= tokens, HorizonStakingInsufficientTokens(prov.tokens, tokens)); + uint256 tokensProvisionTotal = prov.tokens + pool.tokens; + require(tokensProvisionTotal >= tokens, HorizonStakingInsufficientTokens(prov.tokens, tokens)); uint256 tokensToSlash = tokens; uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index b2c256a2d..dd80c878f 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -63,8 +63,8 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { return staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); } - function _deprovision(uint256 amount) internal { - staking.deprovision(users.indexer, subgraphDataServiceAddress, amount); + function _deprovision(uint256 nThawRequests) internal { + staking.deprovision(users.indexer, subgraphDataServiceAddress, nThawRequests); } function _delegate(uint256 amount) internal { diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index ba8584d17..a187dfc6b 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -7,18 +7,46 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDeprovisionTest is HorizonStakingTest { - function testDeprovision_Tokens( + function testDeprovision_AllRequests( uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { skip(thawingPeriod + 1); - _deprovision(amount); + // nThawRequests == 0 removes all thaw requests + _deprovision(0); uint256 idleStake = staking.getIdleStake(users.indexer); assertEq(idleStake, amount); } + function testDeprovision_FirstRequestOnly( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + thawAmount = bound(thawAmount, MIN_DELEGATION, amount); + uint256 thawAmount1 = thawAmount / 2; + bytes32 thawRequestId = _createThawRequest(thawAmount1); + bytes32 thawRequestId2 = _createThawRequest(thawAmount - thawAmount1); + skip(thawingPeriod + 1); + + console.log("thawAmount1: ", thawAmount1); + console.log("thawAmount2: ", thawAmount - thawAmount1); + + ThawRequest memory thawRequest1 = staking.getThawRequest(thawRequestId); + ThawRequest memory thawRequest2 = staking.getThawRequest(thawRequestId2); + console.log("Thaw request 1 shares: ", thawRequest1.shares); + console.log("Thaw request 2 shares: ", thawRequest2.shares); + + console.log("Idle stake before deprovision: ", staking.getIdleStake(users.indexer)); + _deprovision(1); + uint256 idleStake = staking.getIdleStake(users.indexer); + console.log("Idle stake after deprovision: ", idleStake); + assertEq(idleStake, thawAmount1); + } + function testDeprovision_OperatorMovingTokens( uint256 amount, uint32 maxVerifierCut, @@ -26,7 +54,7 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { ) public useOperator useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { skip(thawingPeriod + 1); - _deprovision(amount); + _deprovision(0); uint256 idleStake = staking.getIdleStake(users.indexer); assertEq(idleStake, amount); } @@ -44,54 +72,26 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { subgraphDataServiceAddress ); vm.expectRevert(expectedError); - _deprovision(amount); - } - - function testDeprovision_RevertWhen_ZeroTokens( - uint256 amount, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); - vm.expectRevert(expectedError); _deprovision(0); } - function testDeprovision_RevertWhen_NoThawingTokens( uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - _deprovision(amount); + _deprovision(0); } - function testDeprovision_RevertWhen_StillThawing( + function testDeprovision_StillThawing( uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { vm.assume(thawingPeriod > 0); - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingStillThawing(uint256)", - block.timestamp + thawingPeriod - ); - vm.expectRevert(expectedError); - _deprovision(amount); - } - - function testDeprovision_RevertWhen_NotEnoughThawedTokens( - uint256 amount, - uint32 maxVerifierCut, - uint64 thawingPeriod, - uint256 deprovisionAmount - ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - vm.assume(deprovisionAmount > amount); - skip(thawingPeriod + 1); - - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); - vm.expectRevert(expectedError); - _deprovision(deprovisionAmount); + _deprovision(0); + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, 0); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 78a7a50ac..9cd0c2116 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -9,8 +9,8 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { address private newDataService = makeAddr("newDataService"); - function _reprovision(uint256 amount) private { - staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, amount, 0); + function _reprovision(uint256 tokens, uint256 nThawRequests) private { + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, tokens, nThawRequests); } function testReprovision_MovingTokens( @@ -25,7 +25,9 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { skip(thawingPeriod + 1); _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); - _reprovision(provisionAmount); + + // nThawRequests == 0 reprovisions all thaw requests + _reprovision(provisionAmount, 0); uint256 idleStake = staking.getIdleStake(users.indexer); assertEq(idleStake, 0 ether); @@ -51,7 +53,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { // Switch back to operator vm.startPrank(users.operator); _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); - _reprovision(provisionAmount); + _reprovision(provisionAmount, 0); uint256 idleStake = staking.getIdleStake(users.indexer); assertEq(idleStake, 0 ether); @@ -80,15 +82,15 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { newDataService ); vm.expectRevert(expectedError); - _reprovision(provisionAmount); + _reprovision(provisionAmount, 0); } function testReprovision_RevertWhen_NoThawingTokens( uint256 amount ) public useIndexer useProvision(amount, 0, 0) { - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - _reprovision(amount); + _reprovision(amount, 0); } function testReprovision_RevertWhen_StillThawing( @@ -101,30 +103,11 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { useThawRequest(provisionAmount) { vm.assume(thawingPeriod > 0); - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingStillThawing(uint256)", - block.timestamp + thawingPeriod - ); - vm.expectRevert(expectedError); - _reprovision(provisionAmount); - } - function testReprovision_RevertWhen_NotEnoughThawedTokens( - uint64 thawingPeriod, - uint256 provisionAmount, - uint256 newProvisionAmount - ) - public - useIndexer - useProvision(provisionAmount, 0, thawingPeriod) - useThawRequest(provisionAmount) - { - newProvisionAmount = bound(newProvisionAmount, provisionAmount + 1, type(uint256).max - provisionAmount); - skip(thawingPeriod + 1); + _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); - _createProvision(newDataService, newProvisionAmount, 0, thawingPeriod); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCannotFulfillThawRequest()"); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); vm.expectRevert(expectedError); - _reprovision(newProvisionAmount); + _reprovision(provisionAmount, 0); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index ec2d9e0e5..94785421f 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -41,8 +41,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { assertEq(thawRequest.next, thawRequestId2); ThawRequest memory thawRequest2 = staking.getThawRequest(thawRequestId2); - uint256 totalThawAmount = thawAmount + thawAmount2; - assertEq(thawRequest2.shares, (thawRequest.shares * thawAmount2) / totalThawAmount); + assertEq(thawRequest2.shares, thawAmount2); assertEq(thawRequest2.thawingUntil, block.timestamp + thawingPeriod); } From 5091e7d03fcda1f2b01c289e15f829be3a7ce708 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 28 May 2024 16:07:17 -0300 Subject: [PATCH 086/277] fix: withdraw delegation with zero tokens --- .../contracts/staking/HorizonStaking.sol | 10 ++- packages/horizon/test/GraphBase.t.sol | 2 +- .../test/staking/delegation/withdraw.t.sol | 78 +++++++++++++++++++ 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index f932abc9c..c009f3ebb 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -770,10 +770,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { pool.sharesThawing = sharesThawing; pool.tokensThawing = tokensThawing; - if (_newServiceProvider != address(0)) { - _delegate(_newServiceProvider, _verifier, tokensThawed, _minSharesForNewProvider); - } else { - _graphToken().pushTokens(msg.sender, tokensThawed); + if (tokensThawed != 0) { + if (_newServiceProvider != address(0)) { + _delegate(_newServiceProvider, _verifier, tokensThawed, _minSharesForNewProvider); + } else { + _graphToken().pushTokens(msg.sender, tokensThawed); + } } emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, tokensThawed); diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 27835c54a..565080cc9 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -161,7 +161,7 @@ abstract contract GraphBaseTest is Test, Constants { controller.setPaused(false); } - function createUser(string memory name) private returns (address) { + function createUser(string memory name) internal returns (address) { address user = makeAddr(name); vm.deal({ account: user, newBalance: 100 ether }); deal({ token: address(token), to: user, give: type(uint256).max }); diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 01840874b..b0c6974df 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -36,6 +36,18 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { return (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing; } + function _setupNewIndexer(uint256 tokens) private returns(address) { + address msgSender; + (, msgSender,) = vm.readCallers(); + address newIndexer = createUser("newIndexer"); + vm.startPrank(newIndexer); + token.approve(address(staking), tokens); + staking.stakeTo(newIndexer, tokens); + staking.provision(newIndexer,subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + vm.startPrank(msgSender); + return newIndexer; + } + function testWithdrawDelegation_Tokens( uint256 delegationAmount, uint256 withdrawShares @@ -71,4 +83,70 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { vm.expectRevert(expectedError); _withdrawDelegated(); } + + function testWithdrawDelegation_MoveToNewServiceProvider( + uint256 delegationAmount + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(delegationAmount) + { + Delegation memory thawingDelegation = _getDelegation(); + ThawRequest memory thawRequest = staking.getThawRequest(thawingDelegation.lastThawRequestId); + + skip(thawRequest.thawingUntil + 1); + + // Setup new service provider + address newIndexer = _setupNewIndexer(10_000_000 ether); + + uint256 previousBalance = token.balanceOf(users.delegator); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0); + + uint256 newBalance = token.balanceOf(users.delegator); + assertEq(newBalance, previousBalance); + + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(newIndexer, subgraphDataServiceAddress); + assertEq(delegatedTokens, delegationAmount); + } + + function testWithdrawDelegation_ZeroTokens( + uint256 delegationAmount + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(delegationAmount) + { + uint256 previousBalance = token.balanceOf(users.delegator); + _withdrawDelegated(); + + // Nothing changed since thawing period haven't finished + uint256 newBalance = token.balanceOf(users.delegator); + assertEq(newBalance, previousBalance); + } + + function testWithdrawDelegation_MoveZeroTokensToNewServiceProvider( + uint256 delegationAmount + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(delegationAmount) + { + // Setup new service provider + address newIndexer = _setupNewIndexer(10_000_000 ether); + + uint256 previousBalance = token.balanceOf(users.delegator); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0); + + uint256 newBalance = token.balanceOf(users.delegator); + assertEq(newBalance, previousBalance); + + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(newIndexer, subgraphDataServiceAddress); + assertEq(delegatedTokens, 0); + } } \ No newline at end of file From c212cbed60638b277847ec9e34327d3dcfb11ac7 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 29 May 2024 15:54:51 -0300 Subject: [PATCH 087/277] fix: rebase --- packages/horizon/test/staking/delegation/withdraw.t.sol | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index b0c6974df..0b622ce9a 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -93,16 +93,13 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useDelegation(delegationAmount) useUndelegate(delegationAmount) { - Delegation memory thawingDelegation = _getDelegation(); - ThawRequest memory thawRequest = staking.getThawRequest(thawingDelegation.lastThawRequestId); - - skip(thawRequest.thawingUntil + 1); + skip(MAX_THAWING_PERIOD + 1); // Setup new service provider address newIndexer = _setupNewIndexer(10_000_000 ether); uint256 previousBalance = token.balanceOf(users.delegator); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); uint256 newBalance = token.balanceOf(users.delegator); assertEq(newBalance, previousBalance); @@ -141,7 +138,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { address newIndexer = _setupNewIndexer(10_000_000 ether); uint256 previousBalance = token.balanceOf(users.delegator); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); uint256 newBalance = token.balanceOf(users.delegator); assertEq(newBalance, previousBalance); From d7497d6f73257ec2706ec973ec080b6b62813c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 29 May 2024 16:53:39 -0300 Subject: [PATCH 088/277] docs: add natspec to horizon staking contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/IHorizonStaking.sol | 9 +- .../internal/IHorizonStakingBase.sol | 5 +- .../internal/IHorizonStakingExtension.sol | 10 +- .../internal/IHorizonStakingMain.sol | 815 +++++++++++++++--- .../internal/IHorizonStakingTypes.sol | 124 ++- .../contracts/staking/HorizonStaking.sol | 315 ++++--- .../contracts/staking/HorizonStakingBase.sol | 37 +- .../staking/HorizonStakingExtension.sol | 20 +- .../staking/HorizonStakingStorage.sol | 74 +- .../contracts/staking/utilities/Managed.sol | 22 +- 10 files changed, 1096 insertions(+), 335 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IHorizonStaking.sol b/packages/horizon/contracts/interfaces/IHorizonStaking.sol index 647e66320..1cf1b6283 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStaking.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStaking.sol @@ -4,6 +4,13 @@ pragma solidity 0.8.26; import { IHorizonStakingTypes } from "./internal/IHorizonStakingTypes.sol"; import { IHorizonStakingMain } from "./internal/IHorizonStakingMain.sol"; +import { IHorizonStakingBase } from "./internal/IHorizonStakingBase.sol"; import { IHorizonStakingExtension } from "./internal/IHorizonStakingExtension.sol"; -interface IHorizonStaking is IHorizonStakingTypes, IHorizonStakingMain, IHorizonStakingExtension {} +/** + * @title Complete interface for the Horizon Staking contract + * @notice This interface exposes all functions implemented by the {HorizonStaking} contract and its extension + * {HorizonStakingExtension} as well as the custom data types used by the contract. + * @dev Use this interface to interact with the Horizon Staking contract. + */ +interface IHorizonStaking is IHorizonStakingTypes, IHorizonStakingBase, IHorizonStakingMain, IHorizonStakingExtension {} diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index 563ba258f..808c738f1 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -9,9 +9,8 @@ import { LinkedList } from "../../libraries/LinkedList.sol"; /** * @title Interface for the {HorizonStakingBase} contract. - * @dev Provides getters for {HorizonStaking} and {HorizonStakingExtension} storage variables. - * - * Most functions operate over {HorizonStaking} provisions. To uniquely identify a provision + * @notice Provides getters for {HorizonStaking} and {HorizonStakingExtension} storage variables. + * @dev Most functions operate over {HorizonStaking} provisions. To uniquely identify a provision * functions take `serviceProvider` and `verifier` addresses. */ interface IHorizonStakingBase { diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 4d7518ec4..825ce2292 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -3,12 +3,8 @@ pragma solidity 0.8.26; /** - * @title Base interface for the Staking contract. - * @dev This interface includes only what's implemented in the base Staking contract. - * It does not include the L1 and L2 specific functionality. It also does not include - * several functions that are implemented in the StakingExtension contract, and are called - * via delegatecall through the fallback function. See IStaking.sol for an interface - * that includes the full functionality. + * @title Interface for {HorizonStakingExtension} contract. + * @notice Provides functions for managing legacy allocations and transfer tools. */ interface IHorizonStakingExtension { /** @@ -22,7 +18,7 @@ interface IHorizonStakingExtension { uint256 createdAtEpoch; // Epoch when it was created uint256 closedAtEpoch; // Epoch when it was closed uint256 collectedFees; // Collected fees for the allocation - uint256 DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase + uint256 __DEPRECATED_effectiveAllocation; // solhint-disable-line var-name-mixedcase uint256 accRewardsPerAllocatedToken; // Snapshot used for reward calc uint256 distributedRebates; // Collected rebates that have been rebated } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index cd53cb613..33a8f29cc 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -5,36 +5,43 @@ pragma solidity 0.8.26; import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; -interface IHorizonStakingMain is IHorizonStakingBase { - event ThawRequestCreated( - address indexed serviceProvider, - address indexed verifier, - address indexed owner, - uint256 shares, - uint64 thawingUntil, - bytes32 thawRequestId - ); - event ThawRequestFulfilled(bytes32 indexed thawRequestId, uint256 tokens, uint256 shares, uint64 thawingUntil); - event ThawRequestsFulfilled( - address indexed serviceProvider, - address indexed verifier, - address indexed owner, - uint256 thawRequestsFulfilled, - uint256 tokens - ); +/** + * @title Inferface for the {HorizonStaking} contract. + * @notice Provides functions for managing stake, provisions, delegations, and slashing. + * @dev Note that this interface only includes the functions implemented by {HorizonStaking} contract, + * and not those implemented by {HorizonStakingExtension}. + * Do not use this interface to interface with the {HorizonStaking} contract, use {IHorizonStaking} for + * the complete interface. + * @dev Most functions operate over {HorizonStaking} provisions. To uniquely identify a provision + * functions take `serviceProvider` and `verifier` addresses. + */ +interface IHorizonStakingMain { + // -- Events: stake -- /** - * @dev Emitted when `serviceProvider` withdraws `tokens` amount. + * @notice Emitted when a service provider unstakes tokens during the transition period. + * @param serviceProvider The address of the service provider + * @param tokens The amount of tokens unstaked + * @param until The block number until the stake is locked */ - event StakeWithdrawn(address indexed serviceProvider, uint256 tokens); + event StakeLocked(address indexed serviceProvider, uint256 tokens, uint256 until); /** - * @dev Emitted when `serviceProvider` locks `tokens` amount until `until`. + * @notice Emitted when a service provider withdraws tokens during the transition period. + * @param serviceProvider The address of the service provider + * @param tokens The amount of tokens withdrawn */ - event StakeLocked(address indexed serviceProvider, uint256 tokens, uint256 until); + event StakeWithdrawn(address indexed serviceProvider, uint256 tokens); + + // -- Events: provision -- /** - * @dev Emitted when a service provider provisions staked tokens to a verifier + * @notice Emitted when a service provider provisions staked tokens to a verifier. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens provisioned + * @param maxVerifierCut The maximum cut, expressed in PPM of the slashed amount, that a verifier can take for themselves when slashing + * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ event ProvisionCreated( address indexed serviceProvider, @@ -45,20 +52,108 @@ interface IHorizonStakingMain is IHorizonStakingBase { ); /** - * @dev Emitted when a service provider increases the tokens in a provision + * @notice Emitted whenever staked tokens are added to an existing provision + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens added to the provision */ event ProvisionIncreased(address indexed serviceProvider, address indexed verifier, uint256 tokens); + /** + * @notice Emitted when a service provider thaws tokens from a provision. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens thawed + */ event ProvisionThawed(address indexed serviceProvider, address indexed verifier, uint256 tokens); + /** + * @notice Emitted when a service provider removes tokens from a provision. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens removed + */ event TokensDeprovisioned(address indexed serviceProvider, address indexed verifier, uint256 tokens); + /** + * @notice Emitted when a service provider stages a provision parameter update. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param maxVerifierCut The proposed maximum cut, expressed in PPM of the slashed amount, that a verifier can take for + * themselves when slashing + * @param thawingPeriod The proposed period in seconds that the tokens will be thawing before they can be removed from + * the provision + */ + event ProvisionParametersStaged( + address indexed serviceProvider, + address indexed verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + /** + * @notice Emitted when a service provider accepts a staged provision parameter update. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param maxVerifierCut The new maximum cut, expressed in PPM of the slashed amount, that a verifier can take for themselves + * when slashing + * @param thawingPeriod The new period in seconds that the tokens will be thawing before they can be removed from the provision + */ + event ProvisionParametersSet( + address indexed serviceProvider, + address indexed verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ); + + /** + * @dev Emitted when an operator is allowed or denied by a service provider for a particular verifier + * @param serviceProvider The address of the service provider + * @param operator The address of the operator + * @param verifier The address of the verifier + * @param allowed Whether the operator is allowed or denied + */ + event OperatorSet( + address indexed serviceProvider, + address indexed operator, + address indexed verifier, + bool allowed + ); + + // -- Events: slashing -- + + /** + * @notice Emitted when a provision is slashed by a verifier. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens slashed (note this only represents service provider's slashed stake) + */ event ProvisionSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); + /** + * @notice Emitted when a delegation pool is slashed by a verifier. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens slashed (note this only represents delegation pool's slashed stake) + */ event DelegationSlashed(address indexed serviceProvider, address indexed verifier, uint256 tokens); + /** + * @notice Emitted when a delegation pool would have been slashed by a verifier, but the slashing was skipped + * because delegation slashing global parameter is not enabled. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens that would have been slashed (note this only represents delegation pool's slashed stake) + */ event DelegationSlashingSkipped(address indexed serviceProvider, address indexed verifier, uint256 tokens); + /** + * @notice Emitted when the verifier cut is sent to the verifier after slashing a provision. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param destination The address where the verifier cut is sent + * @param tokens The amount of tokens sent to the verifier + */ event VerifierTokensSent( address indexed serviceProvider, address indexed verifier, @@ -66,6 +161,15 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 tokens ); + // -- Events: delegation -- + + /** + * @notice Emitted when tokens are delegated to a provision. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param delegator The address of the delegator + * @param tokens The amount of tokens delegated + */ event TokensDelegated( address indexed serviceProvider, address indexed verifier, @@ -73,6 +177,14 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 tokens ); + /** + * @notice Emitted when a delegator undelegates tokens from a provision and starts + * thawing them. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param delegator The address of the delegator + * @param tokens The amount of tokens undelegated + */ event TokensUndelegated( address indexed serviceProvider, address indexed verifier, @@ -80,6 +192,13 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 tokens ); + /** + * @notice Emitted when a delegator withdraws tokens from a provision after thawing. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param delegator The address of the delegator + * @param tokens The amount of tokens withdrawn + */ event DelegatedTokensWithdrawn( address indexed serviceProvider, address indexed verifier, @@ -87,99 +206,318 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 tokens ); - event DelegationSlashingEnabled(bool enabled); - - event AllowedLockedVerifierSet(address indexed verifier, bool allowed); - + /** + * @notice Emitted when tokens are added to a delegation pool's reserve. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param tokens The amount of tokens withdrawn + */ event TokensToDelegationPoolAdded(address indexed serviceProvider, address indexed verifier, uint256 tokens); - event ProvisionParametersStaged( + /** + * @notice Emitted when a service provider sets delegation fee cuts for a verifier. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param paymentType The payment type for which the fee cut is set, as defined in {IGraphPayments} + * @param feeCut The fee cut set, in PPM + */ + event DelegationFeeCutSet( address indexed serviceProvider, address indexed verifier, - uint32 maxVerifierCut, - uint64 thawingPeriod + IGraphPayments.PaymentTypes indexed paymentType, + uint256 feeCut ); - event ProvisionParametersSet( + // -- Events: thawing -- + + /** + * @notice Emitted when a thaw request is created. + * @dev Can be emitted by the service provider when thawing stake or by the delegator when undelegating. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param owner The address of the owner of the thaw request. + * @param shares The amount of shares being thawed + * @param thawingUntil The timestamp until the stake is thawed + * @param thawRequestId The ID of the thaw request + */ + event ThawRequestCreated( address indexed serviceProvider, address indexed verifier, - uint32 maxVerifierCut, - uint64 thawingPeriod + address indexed owner, + uint256 shares, + uint64 thawingUntil, + bytes32 thawRequestId ); - event ThawingPeriodCleared(); - event MaxThawingPeriodSet(uint64 maxThawingPeriod); + /** + * @notice Emitted when a thaw request is fulfilled, meaning the stake is released. + * @param thawRequestId The ID of the thaw request + * @param tokens The amount of tokens being released + * @param shares The amount of shares being released + * @param thawingUntil The timestamp until the stake has thawn + */ + event ThawRequestFulfilled(bytes32 indexed thawRequestId, uint256 tokens, uint256 shares, uint64 thawingUntil); /** - * @dev Emitted when an operator is allowed or denied by a service provider for a particular data service + * @notice Emitted when a series of thaw requests are fulfilled. + * @param serviceProvider The address of the service provider + * @param verifier The address of the verifier + * @param owner The address of the owner of the thaw requests + * @param thawRequestsFulfilled The number of thaw requests fulfilled + * @param tokens The total amount of tokens being released */ - event OperatorSet( + event ThawRequestsFulfilled( address indexed serviceProvider, - address indexed operator, address indexed verifier, - bool allowed + address indexed owner, + uint256 thawRequestsFulfilled, + uint256 tokens ); - event DelegationFeeCutSet( - address indexed serviceProvider, - address indexed verifier, - IGraphPayments.PaymentTypes indexed paymentType, - uint256 feeCut - ); + // -- Events: governance -- + + /** + * @notice Emitted when the global maximum thawing period allowed for provisions is set. + * @param maxThawingPeriod The new maximum thawing period + */ + event MaxThawingPeriodSet(uint64 maxThawingPeriod); + + /** + * @notice Emitted when a verifier is allowed or disallowed to be used for locked provisions. + * @param verifier The address of the verifier + * @param allowed Whether the verifier is allowed or disallowed + */ + event AllowedLockedVerifierSet(address indexed verifier, bool allowed); + + /** + * @notice Emitted when the legacy global thawing period is set to zero. + * @dev This marks the end of the transition period. + */ + event ThawingPeriodCleared(); + + /** + * @notice Emitted when the delegation slashing global flag is set. + * @param enabled Whether delegation slashing is enabled or disabled. + */ + event DelegationSlashingEnabled(bool enabled); + // -- Errors: tokens + + /** + * @notice Thrown when operating a zero token amount is not allowed. + */ error HorizonStakingInvalidZeroTokens(); + + /** + * @notice Thrown when a minimum token amount is required to operate but it's not met. + * @param tokens The actual token amount + * @param minRequired The minimum required token amount + */ + error HorizonStakingInsufficientTokens(uint256 tokens, uint256 minRequired); + + /** + * @notice Thrown when the amount of tokens exceeds the maximum allowed to operate. + * @param tokens The actual token amount + * @param maxTokens The maximum allowed token amount + */ + error HorizonStakingTooManyTokens(uint256 tokens, uint256 maxTokens); + + // -- Errors: provision -- + + /** + * @notice Thrown when attempting to operate with a provision that does not exist. + * @param serviceProvider The service provider address + * @param verifier The verifier address + */ error HorizonStakingInvalidProvision(address serviceProvider, address verifier); - error HorizonStakingInvalidTokens(uint256 tokens, uint256 minTokens); - error HorizonStakingInvalidMaxVerifierCut(uint32 maxVerifierCut, uint32 maxAllowedCut); - error HorizonStakingInvalidThawingPeriod(uint64 thawingPeriod, uint64 maxThawingPeriod); + + /** + * @notice Thrown when the caller is not authorized to operate on a provision. + * @param caller The caller address + * @param serviceProvider The service provider address + * @param verifier The verifier address + */ error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); - error HorizonStakingInsufficientCapacity(); - error HorizonStakingInsufficientCapacityForLegacyAllocations(); - error HorizonStakingInsufficientTokensAvailable(uint256 tokensAvailable, uint256 tokensRequired); - error HorizonStakingInsufficientTokens(uint256 available, uint256 tokensRequired); - error HorizonStakingSlippageProtection(uint256 minExpectedShares, uint256 actualShares); - error HorizonStakingVerifierNotAllowed(address verifier); - error HorizonStakingVerifierTokensTooHigh(uint256 tokensVerifier, uint256 maxVerifierTokens); - error HorizonStakingNotEnoughDelegation(uint256 tokensAvailable, uint256 tokensRequired); + + /** + * @notice Thrown when attempting to create a provision with an invalid maximum verifier cut. + * @param maxVerifierCut The maximum verifier cut + * @param maxMaxVerifierCut The maximum `maxVerifierCut` allowed + */ + error HorizonStakingInvalidMaxVerifierCut(uint32 maxVerifierCut, uint32 maxMaxVerifierCut); + + /** + * @notice Thrown when attempting to create a provision with an invalid thawing period. + * @param thawingPeriod The thawing period + * @param maxThawingPeriod The maximum `thawingPeriod` allowed + */ + error HorizonStakingInvalidThawingPeriod(uint64 thawingPeriod, uint64 maxThawingPeriod); + + // -- Errors: stake -- + + /** + * @notice Thrown when the service provider has insufficient idle stake to operate. + * @param tokens The actual token amount + * @param minTokens The minimum required token amount + */ + error HorizonStakingInsufficientIdleStake(uint256 tokens, uint256 minTokens); + + /** + * @notice Thrown during the transition period when the service provider has insufficient stake to + * cover their existing legacy allocations. + * @param tokens The actual token amount + * @param minTokens The minimum required token amount + */ + error HorizonStakingInsufficientStakeForLegacyAllocations(uint256 tokens, uint256 minTokens); + + // -- Errors: delegation -- + + /** + * @notice Thrown when delegation shares obtained are below the expected amount. + * @param shares The actual share amount + * @param minShares The minimum required share amount + */ + error HorizonStakingSlippageProtection(uint256 shares, uint256 minShares); + + /** + * @notice Thrown when operating a zero share amount is not allowed. + */ error HorizonStakingInvalidZeroShares(); - error HorizonStakingInvalidSharesAmount(uint256 sharesAvailable, uint256 sharesRequired); - error HorizonStakingCallerIsServiceProvider(); - error HorizonStakingStillThawing(uint256 until); - error HorizonStakingCannotFulfillThawRequest(); + + /** + * @notice Thrown when a minimum share amount is required to operate but it's not met. + * @param shares The actual share amount + * @param minShares The minimum required share amount + */ + error HorizonStakingInsufficientShares(uint256 shares, uint256 minShares); + + // -- Errors: slashing -- + /** + * @notice Thrown when delegation pool reserves are not enough to cover slashing amount. + * @param tokens The actual token amount in the delegation pool + * @param tokensToSlash The amount to be slashed + */ + error HorizonStakingNotEnoughDelegation(uint256 tokens, uint256 tokensToSlash); + + // -- Errors: thaw requests -- error HorizonStakingNothingThawing(); error HorizonStakingTooManyThawRequests(); - // deposit stake + // -- Errors: misc -- + /** + * @notice Thrown during the transition period when attempting to withdraw tokens that are still thawing. + * @dev Note this thawing refers to the global thawing period applied to legacy allocated tokens, + * it does not refer to thaw requests. + * @param until The block number until the stake is locked + */ + error HorizonStakingStillThawing(uint256 until); + + /** + * @notice Thrown when a service provider attempts to operate on verifieres that are not allowed. + * @dev Only applies to stake from locked wallets. + */ + error HorizonStakingVerifierNotAllowed(address verifier); + + /** + * @notice Thrown when a service provider attempts to change their own operator access. + */ + error HorizonStakingCallerIsServiceProvider(); + + // -- Functions -- + + /** + * @notice Deposit tokens on the staking contract. + * @dev Pulls tokens from the caller. + * + * Requirements: + * - `_tokens` cannot be zero. + * - Caller must have previously approved this contract to pull tokens from their balance. + * + * Emits a {StakeDeposited} event. + * + * @param tokens Amount of tokens to stake + */ function stake(uint256 tokens) external; + /** + * @notice Deposit tokens on the service provider stake, on behalf of the service provider. + * @dev Pulls tokens from the caller. + * + * Requirements: + * - `_tokens` cannot be zero. + * - Caller must have previously approved this contract to pull tokens from their balance. + * + * Emits a {StakeDeposited} event. + * + * @param serviceProvider Address of the service provider + * @param tokens Amount of tokens to stake + */ function stakeTo(address serviceProvider, uint256 tokens) external; // can be called by anyone if the service provider has provisioned stake to this verifier + /** + * @notice Deposit tokens on the service provider stake, on behalf of the service provider, + * provisioned to a specific verifier. + * @dev Requirements: + * - The `serviceProvider` must have previously provisioned stake to `verifier`. + * - `_tokens` cannot be zero. + * - Caller must have previously approved this contract to pull tokens from their balance. + * + * Emits {StakeDeposited} and {ProvisionIncreased} events. + * + * @param serviceProvider Address of the service provider + * @param verifier Address of the verifier + * @param tokens Amount of tokens to stake + */ function stakeToProvision(address serviceProvider, address verifier, uint256 tokens) external; - // create a provision - function provision( - address serviceProvider, - address verifier, - uint256 tokens, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) external; + /** + * @notice Move idle stake back to the owner's account. + * Stake is removed from the protocol: + * - During the transition period it's locked for a period of time before it can be withdrawn + * by calling {withdraw}. + * - After the transition period it's immediately withdrawn. + * @dev Requirements: + * - `_tokens` cannot be zero. + * - `_serviceProvider` must have enough idle stake to cover the staking amount and any + * legacy allocation. + * + * Emits a {StakeLocked} event during the transition period. + * Emits a {StakeWithdrawn} event after the transition period. + * + * @param tokens Amount of tokens to unstake + */ + function unstake(uint256 tokens) external; + + /** + * @notice Withdraw service provider tokens once the thawing period (initiated by {unstake}) has passed. + * All thawed tokens are withdrawn. + * @dev This is only needed during the transition period while we still have + * a global lock. After that, unstake() will automatically withdraw. + */ + function withdraw() external; /** - * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period + * @notice Provision stake to a verifier. The tokens will be locked with a thawing period * and will be slashable by the verifier. This is the main mechanism to provision stake to a data - * service, where the data service is the verifier. Only authorized verifiers can be used. + * service, where the data service is the verifier. * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. + * @dev Requirements: + * - `tokens` cannot be zero and must be over the data service minimum required. + * - Provision parameters must be within the range allowed by the verifier (`maxVerifierCut` and `thawingPeriod`) + * - The `serviceProvider` must have enough idle stake to cover the tokens to provision. + * + * Emits a {ProvisionCreated} event. + * * @param serviceProvider The service provider address * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) * @param tokens The amount of tokens that will be locked and slashable * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ - function provisionLocked( + function provision( address serviceProvider, address verifier, uint256 tokens, @@ -187,16 +525,80 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint64 thawingPeriod ) external; - // initiate a thawing to remove tokens from a provision - function thaw(address serviceProvider, address verifier, uint256 tokens) external returns (bytes32); - - // add more tokens from idle stake to an existing provision + /** + * @notice Adds tokens from the service provider's idle stake to a provision + * @dev + * + * Requirements: + * - The `serviceProvider` must have previously provisioned stake to `verifier`. + * - `tokens` cannot be zero. + * - The `serviceProvider` must have enough idle stake to cover the tokens to add. + * + * Emits a {ProvisionIncreased} event. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param tokens The amount of tokens to add to the provision + */ function addToProvision(address serviceProvider, address verifier, uint256 tokens) external; - // moves thawed stake from a provision back into the provider's available stake + /** + * @notice Start thawing tokens to remove them from a provision. + * This function can be called by the service provider or by an operator authorized by the provider + * for this specific verifier. + * + * Note that removing tokens from a provision is a two step process: + * - First the tokens are thawed using this function. + * - Then after the thawing period, the tokens are removed from the provision using {deprovision} + * or {reprovision}. + * + * @dev Requirements: + * - The provision must have enough tokens available to thaw. + * - `tokens` cannot be zero. + * + * Emits {ProvisionThawed} and {ThawRequestCreated} events. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to thaw + * @return The ID of the thaw request + */ + function thaw(address serviceProvider, address verifier, uint256 tokens) external returns (bytes32); + + /** + * @notice Remove tokens from a provision and move them back to the service provider's idle stake. + * @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw + * requests in the event that fulfulling all of them results in a gas limit error. + * + * Requirements: + * - Must have previously initiated a thaw request using {thaw}. + * + * Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {TokensDeprovisioned} events. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param nThawRequests The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests. + */ function deprovision(address serviceProvider, address verifier, uint256 nThawRequests) external; - // moves thawed stake from one provision into another provision + /** + * @notice Move already thawed stake from one provision into another provision + * This function can be called by the service provider or by an operator authorized by the provider + * for the two corresponding verifiers. + * @dev Requirements: + * - Must have previously initiated a thaw request using {thaw}. + * - `tokens` cannot be zero. + * - The `serviceProvider` must have previously provisioned stake to `newVerifier`. + * - The `serviceProvider` must have enough idle stake to cover the tokens to add. + * + * Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled}, {TokensDeprovisioned} and {ProvisionIncreased} + * events. + * + * @param serviceProvider The service provider address + * @param oldVerifier The verifier address for which the tokens are currently provisioned + * @param newVerifier The verifier address for which the tokens will be provisioned + * @param tokens The amount of tokens to move + */ function reprovision( address serviceProvider, address oldVerifier, @@ -205,16 +607,107 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 nThawRequests ) external; - // moves thawed stake back to the owner's account - stake is removed from the protocol - function unstake(uint256 tokens) external; + /** + * @notice Stages a provision parameter update. Note that the change is not effective until the verifier calls + * {acceptProvisionParameters}. + * @dev This two step update process prevents the service provider from changing the parameters + * without the verifier's consent. + * + * Emits a {ProvisionParametersStaged} event. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param maxVerifierCut The proposed maximum cut, expressed in PPM of the slashed amount, that a verifier can take for + * themselves when slashing + * @param thawingPeriod The proposed period in seconds that the tokens will be thawing before they can be removed from + * the provision + */ + function setProvisionParameters( + address serviceProvider, + address verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external; + + /** + * @notice Accepts a staged provision parameter update. + * @dev Only the provision's verifier can call this function. + * + * Emits a {ProvisionParametersSet} event. + * + * @param serviceProvider The service provider address + */ + function acceptProvisionParameters(address serviceProvider) external; - // delegate tokens to a provider on a data service + /** + * @notice Delegate tokens to a provision. + * @dev Requirements: + * - `tokens` cannot be zero. + * - Caller must have previously approved this contract to pull tokens from their balance. + * - The provision must exist. + * + * Emits a {TokensDelegated} event. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param tokens The amount of tokens to delegate + * @param minSharesOut The minimum amount of shares to accept, slippage protection. + */ function delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) external; - // undelegate (thaw) delegated tokens from a provision + /** + * @notice Add tokens to a delegation pool without issuing shares. + * Used by data services to pay delegation fees/rewards. + * Delegators SHOULD NOT call this function. + * + * @dev Requirements: + * - `tokens` cannot be zero. + * + * Emits a {TokensToDelegationPoolAdded} event. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address for which the tokens are provisioned + * @param tokens The amount of tokens to add to the delegation pool + */ + function addToDelegationPool(address serviceProvider, address verifier, uint256 tokens) external; + + /** + * @notice Undelegate tokens from a provision and start thawing them. + * Note that undelegating tokens from a provision is a two step process: + * - First the tokens are thawed using this function. + * - Then after the thawing period, the tokens are removed from the provision using {withdrawDelegated}. + * + * Requirements: + * - Must have previously initiated a thaw request using {undelegate}. + * - `shares` cannot be zero. + * + * Emits a {TokensUndelegated} and {ThawRequestCreated} event. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param shares The amount of shares to undelegate + * @return The ID of the thaw request + */ function undelegate(address serviceProvider, address verifier, uint256 shares) external returns (bytes32); - // withdraw delegated tokens after thawing + /** + * @notice Withdraw undelegated tokens from a provision after thawing. + * Tokens can be automatically re-delegated to another provision by setting `newServiceProvider`. + * @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw + * requests in the event that fulfulling all of them results in a gas limit error. + * + * Requirements: + * - Must have previously initiated a thaw request using {undelegate}. + * - `newServiceProvider` must either be zero address or have previously provisioned stake to `verifier`. + * + * Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {DelegatedTokensWithdrawn} events. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param newServiceProvider The address of a new service provider, if the delegator wants to re-delegate + * @param minSharesForNewProvider The minimum amount of shares to accept for the new service provider + * @param nThawRequests The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests. + */ function withdrawDelegated( address serviceProvider, address verifier, @@ -223,75 +716,157 @@ interface IHorizonStakingMain is IHorizonStakingBase { uint256 nThawRequests ) external; - function slash( + /** + * @notice Set the fee cut for a verifier on a specific payment type. + * @dev Emits a {DelegationFeeCutSet} event. + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param paymentType The payment type for which the fee cut is set, as defined in {IGraphPayments} + * @param feeCut The fee cut to set, in PPM + */ + function setDelegationFeeCut( address serviceProvider, - uint256 tokens, - uint256 tokensVerifier, - address verifierDestination + address verifier, + IGraphPayments.PaymentTypes paymentType, + uint256 feeCut ) external; /** - * @notice Withdraw service provider tokens once the thawing period has passed. - * @dev This is only needed during the transition period while we still have - * a global lock. After that, unstake() will also withdraw. + * @notice Delegate tokens to the subgraph data service provision. + * This function is for backwards compatibility with the legacy staking contract. + * It only allows delegting to the subgraph data service and DOES NOT have slippage protection. + * @dev See {delegate}. + * @param serviceProvider The service provider address + * @param tokens The amount of tokens to delegate */ - function withdraw() external; + function delegate(address serviceProvider, uint256 tokens) external; - function setDelegationSlashingEnabled(bool enabled) external; + /** + * @notice Undelegate tokens from the subgraph data service provision and start thawing them. + * This function is for backwards compatibility with the legacy staking contract. + * It only allows undelegting from the subgraph data service. + * @dev See {undelegate}. + * @param serviceProvider The service provider address + * @param shares The amount of shares to undelegate + */ + function undelegate(address serviceProvider, uint256 shares) external; - function setMaxThawingPeriod(uint64 maxThawingPeriod) external; + /** + * @notice Withdraw undelegated tokens from the subgraph data service provision after thawing. + * This function is for backwards compatibility with the legacy staking contract. + * It only allows withdrawing from the subgraph data service and DOES NOT have slippage protection in + * case the caller opts for re-delegating. + * @dev See {delegate}. + * @param serviceProvider The service provider address + * @param newServiceProvider The address of a new service provider, if the delegator wants to re-delegate + */ + function withdrawDelegated(address serviceProvider, address newServiceProvider) external; - function setAllowedLockedVerifier(address verifier, bool allowed) external; + /** + * @notice Slash a service provider. This can only be called by a verifier to which + * the provider has provisioned stake, and up to the amount of tokens they have provisioned. + * If the service provider's stake is not enough, the associated delegation pool might be slashed + * depending on the value of the global delegation slashing flag. + * @dev Requirements: + * - `tokens` must be less than or equal to the amount of tokens provisioned by the service provider. + * - `tokensVerifier` must be less than the provision's tokens times the provision's maximum verifier cut. + * + * Emits a {ProvisionSlashed} and {VerifierTokensSent} events. + * Emits a {DelegationSlashed} or {DelegationSlashingSkipped} event depending on the global delegation slashing + * flag. + * + * @param serviceProvider The service provider to slash + * @param tokens The amount of tokens to slash + * @param tokensVerifier The amount of tokens to transfer instead of burning + * @param verifierDestination The address to transfer the verifier cut to + */ + function slash( + address serviceProvider, + uint256 tokens, + uint256 tokensVerifier, + address verifierDestination + ) external; /** - * @notice Add tokens to a delegation pool (without getting shares). - * Used by data services to pay delegation fees/rewards. + * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). + * @dev See {provision}. + * + * Additional requirements: + * - The `verifier` must be allowed to be used for locked provisions. + * * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - * @param tokens The amount of tokens to add to the delegation pool + * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) + * @param tokens The amount of tokens that will be locked and slashable + * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing + * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision */ - function addToDelegationPool(address serviceProvider, address verifier, uint256 tokens) external; - - function setProvisionParameters( + function provisionLocked( address serviceProvider, address verifier, + uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod ) external; - function acceptProvisionParameters(address serviceProvider) external; - /** * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * + * @dev See {setOperator}. + * Additional requirements: + * - The `verifier` must be allowed to be used for locked provisions. + * * @param operator Address to authorize or unauthorize * @param verifier The verifier / data service on which they'll be allowed to operate * @param allowed Whether the operator is authorized or not */ - function setOperator(address operator, address verifier, bool allowed) external; - - // for vesting contracts function setOperatorLocked(address operator, address verifier, bool allowed) external; - function setDelegationFeeCut( - address serviceProvider, - address verifier, - IGraphPayments.PaymentTypes paymentType, - uint256 feeCut - ) external; + /** + * @notice Sets a verifier as a globally allowed verifier for locked provisions. + * @dev This function can only be called by the contract governor, it's used to maintain + * a whitelist of verifiers that do not allow the stake from a locked wallet to escape the lock. + * @dev Emits a {AllowedLockedVerifierSet} event. + * @param verifier The verifier address + * @param allowed Whether the verifier is allowed or not + */ + function setAllowedLockedVerifier(address verifier, bool allowed) external; /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param operator The address to check for auth - * @param serviceProvider The service provider on behalf of whom they're claiming to act - * @param verifier The verifier / data service on which they're claiming to act + * @notice Set the global delegation slashing flag. + * @dev This function can only be called by the contract governor. + * @param enabled Whether delegation slashing is enabled or disabled. */ - function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); + function setDelegationSlashingEnabled(bool enabled) external; + /** + * @notice Clear the legacy global thawing period. + * This signifies the end of the transition period, after which no legacy allocations should be left. + * @dev This function can only be called by the contract governor. + * @dev Emits a {ThawingPeriodCleared} event. + */ function clearThawingPeriod() external; - function delegate(address serviceProvider, uint256 tokens) external; + /** + * @notice Sets the global maximum thawing period allowed for provisions. + * @param maxThawingPeriod The new maximum thawing period, in seconds + */ + function setMaxThawingPeriod(uint64 maxThawingPeriod) external; - function undelegate(address serviceProvider, uint256 shares) external; + /** + * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @dev Emits a {OperatorSet} event. + * @param operator Address to authorize or unauthorize + * @param verifier The verifier / data service on which they'll be allowed to operate + * @param allowed Whether the operator is authorized or not + */ + function setOperator(address operator, address verifier, bool allowed) external; - function withdrawDelegated(address serviceProvider, address newServiceProvider) external; + /** + * @notice Check if an operator is authorized for the caller on a specific verifier / data service. + * @param operator The address to check for auth + * @param serviceProvider The service provider on behalf of whom they're claiming to act + * @param verifier The verifier / data service on which they're claiming to act + * @return Whether the operator is authorized or not + */ + function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index 0b59e0b8c..ae2a05516 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -2,83 +2,139 @@ pragma solidity 0.8.26; -// TODO: create custom var-name-mixedcase +/* solhint-disable var-name-mixedcase */ // TODO: create custom var-name-mixedcase +/** + * @title Defines the data types used in the Horizon staking contract + * @dev In order to preserve storage compatibility some data structures keep deprecated fields. + * These structures have then two representations, an internal one used by the contract storage and a public one. + * Getter functions should retrieve internal representations, remove deprecated fields and return the public representation. + */ interface IHorizonStakingTypes { + /** + * @notice Represents stake assigned to a specific verifier/data service. + * Provisioned stake is locked and can be used as economic security by a data service. + */ struct Provision { - // service provider tokens in the provision + // Service provider tokens in the provision (does not include delegated tokens) uint256 tokens; - // service provider tokens that are being thawed (and will stop being slashable soon) + // Service provider tokens that are being thawed (and will stop being slashable soon) uint256 tokensThawing; - // shares representing the thawing tokens + // Shares representing the thawing tokens uint256 sharesThawing; - // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed + // Max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed uint32 maxVerifierCut; - // time, in seconds, tokens must thaw before being withdrawn + // Time, in seconds, tokens must thaw before being withdrawn uint64 thawingPeriod; + // Timestamp when the provision was created uint64 createdAt; - // max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed + // Pending value for `maxVerifierCut`. Verifier needs to accept it before it becomes active. uint32 maxVerifierCutPending; - // time, in seconds, tokens must thaw before being withdrawn + // Pending value for `thawingPeriod`. Verifier needs to accept it before it becomes active. uint64 thawingPeriodPending; } + /** + * @notice Public representation of a service provider. + * @dev See {ServiceProviderInternal} for the actual storage representation + */ struct ServiceProvider { - // Tokens on the provider stake (staked by the provider) + // Total amount of tokens on the provider stake (only staked by the provider, inludes all provisions) uint256 tokensStaked; - // tokens used in a provision + // Total amount of tokens locked in provisions (only staked by the provider) uint256 tokensProvisioned; } - // the new "Indexer" struct + /** + * @notice Internal representation of a service provider. + * @dev It contains deprecated fields from the `Indexer` struct to maintain storage compatibility. + */ struct ServiceProviderInternal { - // Tokens on the Service Provider stake (staked by the provider) + // Total amount of tokens on the provider stake (only staked by the provider, inludes all provisions) uint256 tokensStaked; - // Tokens used in allocations + // (Deprecated) Tokens used in allocations uint256 __DEPRECATED_tokensAllocated; // solhint-disable-line graph/leading-underscore - // Tokens locked for withdrawal subject to thawing period + // (Deprecated) Tokens locked for withdrawal subject to thawing period uint256 __DEPRECATED_tokensLocked; - // Block when locked tokens can be withdrawn + // (Deprecated) Block when locked tokens can be withdrawn uint256 __DEPRECATED_tokensLockedUntil; - // tokens used in a provision + // Total amount of tokens locked in provisions (only staked by the provider) uint256 tokensProvisioned; } + /** + * @notice Public representation of a delegation pool. + * @dev See {DelegationPoolInternal} for the actual storage representation + */ struct DelegationPool { - uint256 tokens; // Total tokens as pool reserves - uint256 shares; // Total shares minted in the pool - uint256 tokensThawing; // Tokens thawing in the pool - uint256 sharesThawing; // Shares representing the thawing tokens + // Total tokens as pool reserves + uint256 tokens; + // Total shares minted in the pool + uint256 shares; + // Tokens thawing in the pool + uint256 tokensThawing; + // Shares representing the thawing tokens + uint256 sharesThawing; } + /** + * @notice Internal representation of a delegation pool. + * @dev It contains deprecated fields from the previous version of the `DelegationPool` struct + * to maintain storage compatibility. + */ struct DelegationPoolInternal { + // (Deprecated) Time, in blocks, an indexer must wait before updating delegation parameters uint32 __DEPRECATED_cooldownBlocks; - uint32 __DEPRECATED_indexingRewardCut; // in PPM - uint32 __DEPRECATED_queryFeeCut; // in PPM - uint256 __DEPRECATED_updatedAtBlock; // Block when the pool was last updated - uint256 tokens; // Total tokens as pool reserves - uint256 shares; // Total shares minted in the pool - mapping(address => DelegationInternal) delegators; // Mapping of delegator => Delegation - uint256 tokensThawing; // Tokens thawing in the pool - uint256 sharesThawing; // Shares representing the thawing tokens + // (Deprecated) Percentage of indexing rewards for the delegation pool, in PPM + uint32 __DEPRECATED_indexingRewardCut; + // (Deprecated) Percentage of query fees for the delegation pool, in PPM + uint32 __DEPRECATED_queryFeeCut; + // (Deprecated) Block when the delegation parameters were last updated + uint256 __DEPRECATED_updatedAtBlock; + // Total tokens as pool reserves + uint256 tokens; + // Total shares minted in the pool + uint256 shares; + // Delegation details by delegator + mapping(address delegator => DelegationInternal delegation) delegators; + // Tokens thawing in the pool + uint256 tokensThawing; + // Shares representing the thawing tokens + uint256 sharesThawing; } + /** + * @notice Public representation of delegation details. + * @dev See {DelegationInternal} for the actual storage representation + */ struct Delegation { uint256 shares; // Shares owned by a delegator in the pool } + /** + * @notice Internal representation of delegation details. + * @dev It contains deprecated fields from the previous version of the `Delegation` struct + * to maintain storage compatibility. + */ struct DelegationInternal { - uint256 shares; // Shares owned by a delegator in the pool - uint256 __DEPRECATED_tokensLocked; // Tokens locked for undelegation - uint256 __DEPRECATED_tokensLockedUntil; // Epoch when locked tokens can be withdrawn + // Shares owned by the delegator in the pool + uint256 shares; + // (Deprecated) Tokens locked for undelegation + uint256 __DEPRECATED_tokensLocked; + // (Deprecated) Epoch when locked tokens can be withdrawn + uint256 __DEPRECATED_tokensLockedUntil; } + /** + * @notice Details of a stake thawing operation. + * @dev ThawRequests are stored in linked lists by service provider/delegator. + */ struct ThawRequest { - // shares that represent the tokens being thawed + // Shares that represent the tokens being thawed uint256 shares; - // the timestamp when the thawed funds can be removed from the provision + // The timestamp when the thawed funds can be removed from the provision uint64 thawingUntil; - // id of the next thaw request in the linked list + // Id of the next thaw request in the linked list bytes32 next; } } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 939200cf4..015ea5bcc 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -15,13 +15,15 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; /** * @title HorizonStaking contract - * @dev This contract is the main Staking contract in The Graph protocol after the Horizon upgrade. - * It is designed to be deployed as an upgrade to the L2Staking contract from the legacy contracts - * package. - * @dev It uses a HorizonStakingExtension contract to implement the full IHorizonStaking interface through delegatecalls. - * This is due to the contract size limit on Arbitrum (24kB). The extension contract contains functionality to support - * the legacy staking functions and the transfer tools. Both can be eventually safely removed without affecting - * the main staking contract. + * @notice The {HorizonStaking} contract allows service providers to stake and provision tokens to verifiers to be used + * as economic security for a service. It also allows delegators to delegate towards a service provider provision. + * @dev Implements the {IHorizonStakingMain} interface. + * @dev This is the main Staking contract in The Graph protocol after the Horizon upgrade. + * It is designed to be deployed as an upgrade to the L2Staking contract from the legacy contracts package. + * @dev It uses a {HorizonStakingExtension} contract to implement the full {IHorizonStaking} interface through delegatecalls. + * This is due to the contract size limit on Arbitrum (24kB). The extension contract implements functionality to support + * the legacy staking functions and the transfer tools. Both can be eventually removed without affecting the main + * staking contract. */ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { using TokenUtils for IGraphToken; @@ -46,8 +48,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /// (delegation on L2 has its own slippage protection) uint256 private constant MIN_DELEGATION = 1e18; + /// @dev Address of the staking extension contract address private immutable STAKING_EXTENSION_ADDRESS; + /** + * @notice Checks that the caller is authorized to operate over a provision. + * @param serviceProvider The address of the service provider. + * @param verifier The address of the verifier. + */ modifier onlyAuthorized(address serviceProvider, address verifier) { require( _isAuthorized(msg.sender, serviceProvider, verifier), @@ -56,6 +64,13 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _; } + /** + * @dev The staking contract is upgradeable however we stil use the constructor to set + * a few immutable variables. + * @param controller The address of the Graph controller contract. + * @param stakingExtensionAddress The address of the staking extension contract. + * @param subgraphDataServiceAddress The address of the subgraph data service. + */ constructor( address controller, address stakingExtensionAddress, @@ -103,28 +118,21 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { */ /** - * @notice Deposit tokens on the caller's stake. - * @param tokens Amount of tokens to stake + * @notice See {IHorizonStakingMain-stake}. */ function stake(uint256 tokens) external override notPaused { _stakeTo(msg.sender, tokens); } /** - * @notice Deposit tokens on the service provider stake, on behalf of the service provider. - * @param serviceProvider Address of the service provider - * @param tokens Amount of tokens to stake + * @notice See {IHorizonStakingMain-stakeTo}. */ function stakeTo(address serviceProvider, uint256 tokens) external override notPaused { _stakeTo(serviceProvider, tokens); } /** - * @notice Deposit tokens on the service provider stake, on behalf of the service provider, provisioned - * to a specific verifier. The provider must have previously provisioned stake to that verifier. - * @param serviceProvider Address of the service provider - * @param verifier Address of the verifier - * @param tokens Amount of tokens to stake + * @notice See {IHorizonStakingMain-stakeToProvision}. */ function stakeToProvision(address serviceProvider, address verifier, uint256 tokens) external override notPaused { _stakeTo(serviceProvider, tokens); @@ -132,22 +140,17 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @notice Move idle stake back to the owner's account. - * If tokens were thawing they must be deprovisioned first. - * Stake is removed from the protocol. - * @param tokens Amount of tokens to unstake + * @notice See {IHorizonStakingMain-unstake}. */ function unstake(uint256 tokens) external override notPaused { _unstake(tokens); } /** - * @notice Withdraw service provider tokens once the thawing period has passed. - * @dev This is only needed during the transition period while we still have - * a global lock. After that, unstake() will also withdraw. + * @notice See {IHorizonStakingMain-withdraw}. */ function withdraw() external override notPaused { - _withdraw(msg.sender); + _withdraw(msg.sender, true); } /* @@ -155,16 +158,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { */ /** - * @notice Provision stake to a verifier. The tokens will be locked with a thawing period - * and will be slashable by the verifier. This is the main mechanism to provision stake to a data - * service, where the data service is the verifier. - * This function can be called by the service provider or by an operator authorized by the provider - * for this specific verifier. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) - * @param tokens The amount of tokens that will be locked and slashable - * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing - * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + * @notice See {IHorizonStakingMain-provision}. */ function provision( address serviceProvider, @@ -177,12 +171,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @notice Add more tokens to an existing provision. - * This function can be called by the service provider or by an operator authorized by the provider - * for this specific verifier. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - * @param tokens The amount of tokens to add to the provision + * @notice See {IHorizonStakingMain-addToProvision}. */ function addToProvision( address serviceProvider, @@ -193,12 +182,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @notice Start thawing tokens to remove them from a provision. - * This function can be called by the service provider or by an operator authorized by the provider - * for this specific verifier. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - * @param tokens The amount of tokens to thaw + * @notice See {IHorizonStakingMain-thaw}. */ function thaw( address serviceProvider, @@ -208,7 +192,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { return _thaw(serviceProvider, verifier, tokens); } - // moves thawed stake from a provision back into the provider's available stake + /** + * @notice See {IHorizonStakingMain-deprovision}. + */ function deprovision( address serviceProvider, address verifier, @@ -218,14 +204,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @notice Move already thawed stake from one provision into another provision - * This function can be called by the service provider or by an operator authorized by the provider - * for the two corresponding verifiers. - * The provider must have previously provisioned tokens to the new verifier. - * @param serviceProvider The service provider address - * @param oldVerifier The verifier address for which the tokens are currently provisioned - * @param newVerifier The verifier address for which the tokens will be provisioned - * @param tokens The amount of tokens to move + * @notice See {IHorizonStakingMain-reprovision}. */ function reprovision( address serviceProvider, @@ -244,6 +223,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _addToProvision(serviceProvider, newVerifier, tokens); } + /** + * @notice See {IHorizonStakingMain-setProvisionParameters}. + */ function setProvisionParameters( address serviceProvider, address verifier, @@ -256,6 +238,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); } + /** + * @notice See {IHorizonStakingMain-acceptProvisionParameters}. + */ function acceptProvisionParameters(address serviceProvider) external override notPaused { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; @@ -268,6 +253,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * DELEGATION */ + /** + * @notice See {IHorizonStakingMain-delegate}. + */ function delegate( address serviceProvider, address verifier, @@ -279,11 +267,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @notice Add tokens to a delegation pool (without getting shares). - * Used by data services to pay delegation fees/rewards. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned - * @param tokens The amount of tokens to add to the delegation pool + * @notice See {IHorizonStakingMain-addToDelegationPool}. */ function addToDelegationPool( address serviceProvider, @@ -296,8 +280,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit TokensToDelegationPoolAdded(serviceProvider, verifier, tokens); } - // undelegate tokens from a service provider - // the shares are burned and replaced with shares in the thawing pool + /** + * @notice See {IHorizonStakingMain-undelegate}. + */ function undelegate( address serviceProvider, address verifier, @@ -306,6 +291,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { return _undelegate(serviceProvider, verifier, shares); } + /** + * @notice See {IHorizonStakingMain-withdrawDelegated}. + */ function withdrawDelegated( address serviceProvider, address verifier, @@ -316,6 +304,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _withdrawDelegated(serviceProvider, verifier, newServiceProvider, minSharesForNewProvider, nThawRequests); } + /** + * @notice See {IHorizonStakingMain-setDelegationFeeCut}. + */ function setDelegationFeeCut( address serviceProvider, address verifier, @@ -326,19 +317,24 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); } - // For backwards compatibility, delegates to the subgraph data service - // (Note this one doesn't have splippage/rounding protection!) + /** + * @notice See {IHorizonStakingMain-delegate}. + */ function delegate(address serviceProvider, uint256 tokens) external override notPaused { _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); } - // For backwards compatibility, undelegates from the subgraph data service + /** + * @notice See {IHorizonStakingMain-undelegate}. + */ function undelegate(address serviceProvider, uint256 shares) external override notPaused { _undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); } - // For backwards compatibility, withdraws delegated tokens from the subgraph data service + /** + * @notice See {IHorizonStakingMain-withdrawDelegated}. + */ function withdrawDelegated(address serviceProvider, address newServiceProvider) external override notPaused { _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0, 0); } @@ -348,14 +344,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { */ /** - * @notice Slash a service provider. This can only be called by a verifier to which - * the provider has provisioned stake, and up to the amount of tokens they have provisioned. - * @dev If delegation slashing is disabled, and the amount of tokens is more than the - * provider's provisioned self-stake, the delegation slashing is skipped without reverting. - * @param serviceProvider The service provider to slash - * @param tokens The amount of tokens to slash - * @param tokensVerifier The amount of tokens to transfer instead of burning - * @param verifierDestination The address to transfer the verifier cut to + * @notice See {IHorizonStakingMain-slash}. */ function slash( address serviceProvider, @@ -370,10 +359,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokensToSlash = tokens; uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); if (providerTokensSlashed > 0) { - uint256 maxVerifierCut = prov.tokens.mulPPM(prov.maxVerifierCut); + uint256 maxVerifierTokens = prov.tokens.mulPPM(prov.maxVerifierCut); require( - maxVerifierCut >= tokensVerifier, - HorizonStakingVerifierTokensTooHigh(tokensVerifier, maxVerifierCut) + maxVerifierTokens >= tokensVerifier, + HorizonStakingTooManyTokens(tokensVerifier, maxVerifierTokens) ); if (tokensVerifier > 0) { _graphToken().pushTokens(verifierDestination, tokensVerifier); @@ -418,16 +407,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { */ /** - * @notice Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets). The tokens will be locked with a thawing period - * and will be slashable by the verifier. This is the main mechanism to provision stake to a data - * service, where the data service is the verifier. Only authorized verifiers can be used. - * This function can be called by the service provider or by an operator authorized by the provider - * for this specific verifier. - * @param serviceProvider The service provider address - * @param verifier The verifier address for which the tokens are provisioned (who will be able to slash the tokens) - * @param tokens The amount of tokens that will be locked and slashable - * @param maxVerifierCut The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing - * @param thawingPeriod The period in seconds that the tokens will be thawing before they can be removed from the provision + * @notice See {IHorizonStakingMain-provisionLocked}. */ function provisionLocked( address serviceProvider, @@ -440,7 +420,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _createProvision(serviceProvider, tokens, verifier, maxVerifierCut, thawingPeriod); } - // for vesting contracts + /** + * @notice See {IHorizonStakingMain-setOperatorLocked}. + */ function setOperatorLocked(address operator, address verifier, bool allowed) external override notPaused { require(_allowedLockedVerifiers[verifier], HorizonStakingVerifierNotAllowed(verifier)); _setOperator(operator, verifier, allowed); @@ -450,22 +432,33 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * GOVERNANCE */ + /** + * @notice See {IHorizonStakingMain-setAllowedLockedVerifier}. + */ function setAllowedLockedVerifier(address verifier, bool allowed) external override onlyGovernor { _allowedLockedVerifiers[verifier] = allowed; emit AllowedLockedVerifierSet(verifier, allowed); } + /** + * @notice See {IHorizonStakingMain-setDelegationSlashingEnabled}. + */ function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { _delegationSlashingEnabled = enabled; emit DelegationSlashingEnabled(enabled); } - // To be called at the end of the transition period, to set the deprecated thawing period to 0 + /** + * @notice See {IHorizonStakingMain-clearThawingPeriod}. + */ function clearThawingPeriod() external override onlyGovernor { __DEPRECATED_thawingPeriod = 0; emit ThawingPeriodCleared(); } + /** + * @notice See {IHorizonStakingMain-setMaxThawingPeriod}. + */ function setMaxThawingPeriod(uint64 maxThawingPeriod) external override onlyGovernor { _maxThawingPeriod = maxThawingPeriod; emit MaxThawingPeriodSet(_maxThawingPeriod); @@ -476,20 +469,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { */ /** - * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. - * @param operator Address to authorize or unauthorize - * @param verifier The verifier / data service on which they'll be allowed to operate - * @param allowed Whether the operator is authorized or not + * @notice See {IHorizonStakingMain-setOperator}. */ function setOperator(address operator, address verifier, bool allowed) external override notPaused { _setOperator(operator, verifier, allowed); } /** - * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param operator The address to check for auth - * @param serviceProvider The service provider on behalf of whom they're claiming to act - * @param verifier The verifier / data service on which they're claiming to act + * @notice See {IHorizonStakingMain-isAuthorized}. */ function isAuthorized( address operator, @@ -502,6 +489,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /* * PRIVATE FUNCTIONS */ + + /** + * @notice See {IHorizonStakingMain-stakeTo}. + */ function _stakeTo(address _serviceProvider, uint256 _tokens) private { require(_tokens != 0, HorizonStakingInvalidZeroTokens()); @@ -512,10 +503,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _stake(_serviceProvider, _tokens); } + /** + * @notice See {IHorizonStakingMain-unstake}. + */ function _unstake(uint256 _tokens) private { address serviceProvider = msg.sender; require(_tokens != 0, HorizonStakingInvalidZeroTokens()); - require(_tokens <= _getIdleStake(serviceProvider), HorizonStakingInsufficientCapacity()); + uint256 tokensIdle = _getIdleStake(serviceProvider); + require(_tokens <= tokensIdle, HorizonStakingInsufficientIdleStake(_tokens, tokensIdle)); ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; uint256 stakedTokens = sp.tokensStaked; @@ -523,9 +518,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // to cover existing allocations // TODO this is only needed until legacy allocations are closed, // so we should remove it after the transition period + uint256 remainingTokens = stakedTokens - _tokens; require( - stakedTokens - _tokens >= sp.__DEPRECATED_tokensAllocated, - HorizonStakingInsufficientCapacityForLegacyAllocations() + remainingTokens >= sp.__DEPRECATED_tokensAllocated, + HorizonStakingInsufficientStakeForLegacyAllocations(remainingTokens, sp.__DEPRECATED_tokensAllocated) ); // This is also only during the transition period: we need @@ -540,7 +536,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } else { // Before locking more tokens, withdraw any unlocked ones if possible if (sp.__DEPRECATED_tokensLockedUntil != 0 && block.number >= sp.__DEPRECATED_tokensLockedUntil) { - _withdraw(serviceProvider); + _withdraw(serviceProvider, false); } // TODO remove after the transition period // Take into account period averaging for multiple unstake requests @@ -561,18 +557,24 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @dev Withdraw service provider tokens once the thawing period has passed. + * @notice See {IHorizonStakingMain-withdraw}. * @param _serviceProvider Address of service provider to withdraw funds from + * @param revertIfThawing If true, the function will revert if the tokens are still thawing */ - function _withdraw(address _serviceProvider) private { + function _withdraw(address _serviceProvider, bool revertIfThawing) private { // Get tokens available for withdraw and update balance ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; - require(tokensToWithdraw > 0, HorizonStakingInvalidZeroTokens()); - require( - block.timestamp >= sp.__DEPRECATED_tokensLockedUntil, - HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) - ); + require(tokensToWithdraw != 0, HorizonStakingInvalidZeroTokens()); + + if (revertIfThawing) { + require( + block.timestamp >= sp.__DEPRECATED_tokensLockedUntil, + HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) + ); + } else { + return; + } // Reset locked tokens sp.__DEPRECATED_tokensLocked = 0; @@ -587,7 +589,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @dev Creates a provision + * @notice See {IHorizonStakingMain-createProvision}. */ function _createProvision( address _serviceProvider, @@ -596,7 +598,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 _maxVerifierCut, uint64 _thawingPeriod ) private { - require(_tokens >= MIN_PROVISION_SIZE, HorizonStakingInvalidTokens(_tokens, MIN_PROVISION_SIZE)); + require(_tokens >= MIN_PROVISION_SIZE, HorizonStakingInsufficientTokens(_tokens, MIN_PROVISION_SIZE)); require( _maxVerifierCut <= MAX_MAX_VERIFIER_CUT, HorizonStakingInvalidMaxVerifierCut(_maxVerifierCut, MAX_MAX_VERIFIER_CUT) @@ -605,7 +607,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _thawingPeriod <= _maxThawingPeriod, HorizonStakingInvalidThawingPeriod(_thawingPeriod, _maxThawingPeriod) ); - require(_tokens <= _getIdleStake(_serviceProvider), HorizonStakingInsufficientCapacity()); + uint256 tokensIdle = _getIdleStake(_serviceProvider); + require(_tokens <= tokensIdle, HorizonStakingInsufficientIdleStake(_tokens, tokensIdle)); _provisions[_serviceProvider][_verifier] = Provision({ tokens: _tokens, @@ -624,11 +627,15 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit ProvisionCreated(_serviceProvider, _verifier, _tokens, _maxVerifierCut, _thawingPeriod); } + /** + * @notice See {IHorizonStakingMain-addToProvision}. + */ function _addToProvision(address _serviceProvider, address _verifier, uint256 _tokens) private { Provision storage prov = _provisions[_serviceProvider][_verifier]; require(_tokens != 0, HorizonStakingInvalidZeroTokens()); require(prov.createdAt != 0, HorizonStakingInvalidProvision(_serviceProvider, _verifier)); - require(_tokens <= _getIdleStake(_serviceProvider), HorizonStakingInsufficientCapacity()); + uint256 tokensIdle = _getIdleStake(_serviceProvider); + require(_tokens <= tokensIdle, HorizonStakingInsufficientIdleStake(_tokens, tokensIdle)); prov.tokens = prov.tokens + _tokens; _serviceProviders[_serviceProvider].tokensProvisioned = @@ -637,16 +644,18 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit ProvisionIncreased(_serviceProvider, _verifier, _tokens); } + /** + * @notice See {IHorizonStakingMain-thaw}. + */ function _thaw(address _serviceProvider, address _verifier, uint256 _tokens) private returns (bytes32) { require(_tokens != 0, HorizonStakingInvalidZeroTokens()); uint256 tokensAvailable = _getProviderTokensAvailable(_serviceProvider, _verifier); - require(tokensAvailable >= _tokens, HorizonStakingInsufficientTokensAvailable(tokensAvailable, _tokens)); + require(tokensAvailable >= _tokens, HorizonStakingInsufficientTokens(tokensAvailable, _tokens)); Provision storage prov = _provisions[_serviceProvider][_verifier]; uint256 thawingShares = prov.sharesThawing == 0 ? _tokens : (prov.sharesThawing * _tokens) / prov.tokensThawing; uint64 thawingUntil = uint64(block.timestamp + uint256(prov.thawingPeriod)); - // provision accounting prov.tokensThawing = prov.tokensThawing + _tokens; prov.sharesThawing = prov.sharesThawing + thawingShares; @@ -661,6 +670,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { return thawRequestId; } + /** + * @notice See {IHorizonStakingMain-deprovision}. + */ function _deprovision(address _serviceProvider, address _verifier, uint256 _nThawRequests) private { Provision storage prov = _provisions[_serviceProvider][_verifier]; @@ -684,13 +696,18 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit TokensDeprovisioned(_serviceProvider, _verifier, tokensThawed); } + /** + * @notice See {IHorizonStakingMain-delegate}. + * @dev Note that this function does not pull the delegated tokens from the caller. It expects that to + * have been done before calling this function. + */ function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) private { require(_tokens != 0, HorizonStakingInvalidZeroTokens()); // TODO: remove this after L2 transfer tool for delegation is removed - require(_tokens >= MIN_DELEGATION, HorizonStakingInsufficientTokens(MIN_DELEGATION, _tokens)); + require(_tokens >= MIN_DELEGATION, HorizonStakingInsufficientTokens(_tokens, MIN_DELEGATION)); require( - _provisions[_serviceProvider][_verifier].tokens != 0, + _provisions[_serviceProvider][_verifier].createdAt != 0, HorizonStakingInvalidProvision(_serviceProvider, _verifier) ); @@ -699,7 +716,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // Calculate shares to issue uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); - require(shares != 0 && shares >= _minSharesOut, HorizonStakingSlippageProtection(_minSharesOut, shares)); + require(shares != 0 && shares >= _minSharesOut, HorizonStakingSlippageProtection(shares, _minSharesOut)); pool.tokens = pool.tokens + _tokens; pool.shares = pool.shares + shares; @@ -709,11 +726,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit TokensDelegated(_serviceProvider, _verifier, msg.sender, _tokens); } + /** + * @notice See {IHorizonStakingMain-undelegate}. + * @dev To allow delegation to be slashable even while thawing without breaking accounting + * the delegation pool shares are burned and replaced with thawing pool shares. + */ function _undelegate(address _serviceProvider, address _verifier, uint256 _shares) private returns (bytes32) { require(_shares > 0, HorizonStakingInvalidZeroShares()); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); DelegationInternal storage delegation = pool.delegators[msg.sender]; - require(delegation.shares >= _shares, HorizonStakingInvalidSharesAmount(delegation.shares, _shares)); + require(delegation.shares >= _shares, HorizonStakingInsufficientShares(delegation.shares, _shares)); uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); @@ -744,6 +766,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { return thawRequestId; } + /** + * @notice See {IHorizonStakingMain-withdrawDelegated}. + */ function _withdrawDelegated( address _serviceProvider, address _verifier, @@ -778,6 +803,19 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit DelegatedTokensWithdrawn(_serviceProvider, _verifier, msg.sender, tokensThawed); } + /** + * @notice Creates a thaw request. + * Allows creating thaw requests up to a maximum of `MAX_THAW_REQUESTS` per owner. + * Thaw requests are stored in a linked list per owner (and service provider, verifier) to allow for efficient + * processing. + * @dev Emits a {ThawRequestCreated} event. + * @param _serviceProvider The address of the service provider + * @param _verifier The address of the verifier + * @param _owner The address of the owner of the thaw request + * @param _shares The number of shares to thaw + * @param _thawingUntil The timestamp until which the shares are thawing + * @return The ID of the thaw request + */ function _createThawRequest( address _serviceProvider, address _verifier, @@ -798,6 +836,19 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { return thawRequestId; } + /** + * @notice Traverses a thaw request list and fulfills expired thaw requests. + * @dev Emits a {ThawRequestsFulfilled} event and a {ThawRequestFulfilled} event for each thaw request fulfilled. + * @param _serviceProvider The address of the service provider + * @param _verifier The address of the verifier + * @param _owner The address of the owner of the thaw request + * @param _tokensThawing The current amount of tokens already thawing + * @param _sharesThawing The current amount of shares already thawing + * @param _nThawRequests The number of thaw requests to fulfill. If set to 0, all thaw requests are fulfilled. + * @return The amount of thawed tokens + * @return The amount of tokens still thawing + * @return The amount of shares still thawing + */ function _fulfillThawRequests( address _serviceProvider, address _verifier, @@ -823,6 +874,17 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { return (tokensThawed, _tokensThawing, _sharesThawing); } + /** + * @notice Fulfills a thaw request. + * @dev This function is used as a callback in the linked list traversal. + * + * Emits a {ThawRequestFulfilled} event. + * + * @param _thawRequestId The ID of the current thaw request + * @return Wether the thaw request is still thawing, indicating that the traversal should continue or stop. + * @return Wether the thaw request should be deleted + * @return The updated accumulator data + */ function _fulfillThawRequest(bytes32 _thawRequestId, bytes memory _acc) private returns (bool, bool, bytes memory) { ThawRequest storage thawRequest = _thawRequests[_thawRequestId]; @@ -849,10 +911,20 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { return (false, true, _acc); } + /** + * @notice Deletes a ThawRequest. + * @dev This function is used as a callback in the linked list traversal. + * @param _thawRequestId The ID of the thaw request to delete + */ function _deleteThawRequest(bytes32 _thawRequestId) private { delete _thawRequests[_thawRequestId]; } + /** + * @notice See {IHorizonStakingMain-setOperator}. + * @dev Note that this function handles the special case where the verifier is the subgraph data service, + * where the operator settings are stored in the legacy mapping. + */ function _setOperator(address _operator, address _verifier, bool _allowed) private { require(_operator != msg.sender, HorizonStakingCallerIsServiceProvider()); if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { @@ -863,6 +935,11 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit OperatorSet(msg.sender, _operator, _verifier, _allowed); } + /** + * @notice See {IHorizonStakingMain-isAuthorized}. + * @dev Note that this function handles the special case where the verifier is the subgraph data service, + * where the operator settings are stored in the legacy mapping. + */ function _isAuthorized(address _operator, address _serviceProvider, address _verifier) private view returns (bool) { if (_operator == _serviceProvider) { return true; diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index e338b9e03..c173c4bec 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -16,8 +16,11 @@ import { HorizonStakingV1Storage } from "./HorizonStakingStorage.sol"; /** * @title HorizonStakingBase contract - * @dev This contract is the base staking contract, to be inherited by HorizonStaking and HorizonStakingExtension. - * It implements all storage getters for both internal and external use. + * @notice This contract is the base staking contract implementing storage getters for both internal + * and external use. + * @dev Implementation of the {IHorizonStakingBase} interface. + * @dev It's meant to be inherited by the {HorizonStaking} and {HorizonStakingExtension} + * contracts so some internal functions are also included here. */ abstract contract HorizonStakingBase is Multicall, @@ -29,8 +32,18 @@ abstract contract HorizonStakingBase is { using LinkedList for LinkedList.List; + /** + * @notice The address of the subgraph data service. + * @dev Require to handle the special case when the verifier is the subgraph data service. + */ address internal immutable SUBGRAPH_DATA_SERVICE_ADDRESS; + /** + * @dev The staking contract is upgradeable however we stil use the constructor to set + * a few immutable variables. + * @param controller The address of the Graph controller contract. + * @param subgraphDataServiceAddress The address of the subgraph data service. + */ constructor(address controller, address subgraphDataServiceAddress) Managed(controller) { SUBGRAPH_DATA_SERVICE_ADDRESS = subgraphDataServiceAddress; } @@ -216,6 +229,8 @@ abstract contract HorizonStakingBase is * needs to be here since it's used by both {HorizonStaking} and {HorizonStakingExtension}. * * Emits a {StakeDeposited} event. + * @param _serviceProvider The address of the service provider. + * @param _tokens The amount of tokens to deposit. */ function _stake(address _serviceProvider, uint256 _tokens) internal { _serviceProviders[_serviceProvider].tokensStaked = _serviceProviders[_serviceProvider].tokensStaked + _tokens; @@ -223,9 +238,8 @@ abstract contract HorizonStakingBase is } /** - * @dev Gets the idle stake of a service provider. - * - * Note that the calculation considers tokens that were locked in the legacy staking contract. + * @notice See {IHorizonStakingBase-getIdleStake}. + * @dev Note that the calculation considers tokens that were locked in the legacy staking contract. * TODO: update the calculation after the transition period. */ function _getIdleStake(address _serviceProvider) internal view returns (uint256) { @@ -236,10 +250,9 @@ abstract contract HorizonStakingBase is } /** - * @dev Gets a delegation pool. - * - * Note that there is a special case if the verifier is the subgraph data service, since - * in that case the pools are stored in the legacy mapping. + * @notice See {IHorizonStakingBase-getDelegationPool}. + * @dev Note that this function handles the special case where the verifier is the subgraph data service, + * where the pools are stored in the legacy mapping. */ function _getDelegationPool( address _serviceProvider, @@ -255,14 +268,14 @@ abstract contract HorizonStakingBase is } /** - * @dev See {IHorizonStakingBase-getProviderTokensAvailable}. + * @notice See {IHorizonStakingBase-getProviderTokensAvailable}. */ function _getProviderTokensAvailable(address _serviceProvider, address _verifier) internal view returns (uint256) { return _provisions[_serviceProvider][_verifier].tokens - _provisions[_serviceProvider][_verifier].tokensThawing; } /** - * @dev See {IHorizonStakingBase-getDelegatedTokensAvailable}. + * @notice See {IHorizonStakingBase-getDelegatedTokensAvailable}. */ function _getDelegatedTokensAvailable(address _serviceProvider, address _verifier) internal view returns (uint256) { DelegationPoolInternal storage poolInternal = _getDelegationPool(_serviceProvider, _verifier); @@ -270,7 +283,7 @@ abstract contract HorizonStakingBase is } /** - * @dev Gets the next thaw request in the list. + * @notice Gets the next thaw request after `_thawRequestId`. */ function _getNextThawRequest(bytes32 _thawRequestId) internal view returns (bytes32) { return _thawRequests[_thawRequestId].next; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 6265583fe..c2d7685b4 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -19,14 +19,12 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; /** * @title Horizon Staking extension contract - * @dev This contract contains: - * - all the legacy staking functionality, required to support the transition period - * - transfer tools support functions - * TODO: once the transition period and the transfer tools are deemed not necessary this contract - * can be removed. - * @dev 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. + * @notice The {HorizonStakingExtension} contract implements the legacy functionality required to support the transition + * to the Horizon Staking contract. It allows indexers to close allocations and collect pending query fees, but it + * does not allow for the creation of new allocations. This should allow indexers to migrate to a subgraph data service + * without losing rewards or having service interruptions. + * @dev TODO: Once the transition period and the transfer tools are deemed not necessary this contract + * can be removed. It's expected the transition period to last for a full allocation cycle (28 epochs). */ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2StakingBase, IHorizonStakingExtension { using TokenUtils for IGraphToken; @@ -43,6 +41,12 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki _; } + /** + * @dev The staking contract is upgradeable however we stil use the constructor to set + * a few immutable variables. + * @param controller The address of the Graph controller contract. + * @param subgraphDataServiceAddress The address of the subgraph data service. + */ constructor( address controller, address subgraphDataServiceAddress diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index c69bbca51..2b58b02c7 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -8,14 +8,15 @@ import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { LinkedList } from "../libraries/LinkedList.sol"; -// TODO: create custom var-name-mixedcase -/* solhint-disable var-name-mixedcase */ +/* solhint-disable var-name-mixedcase */ // TODO: create custom var-name-mixedcase +/* solhint-disable max-states-count */ /** * @title HorizonStakingV1Storage - * @notice This contract holds all the storage variables for the Staking contract, version 1 + * @notice This contract holds all the storage variables for the Staking contract. + * @dev Deprecated variables are kept to support the transition to Horizon Staking. + * They can eventually be collapsed into a single storage slot. */ -// solhint-disable-next-line max-states-count abstract contract HorizonStakingV1Storage { // -- Staking -- @@ -38,34 +39,36 @@ abstract contract HorizonStakingV1Storage { uint32 internal __DEPRECATED_protocolPercentage; /// @dev Period for allocation to be finalized + /// Deprecated with exponential rebates. uint32 private __DEPRECATED_channelDisputeEpochs; - /// @dev Maximum allocation time. Deprecated, allocations now live on the subgraph service contract. + /// @dev Maximum allocation time. + /// Deprecated, allocations now live on the subgraph service contract. uint32 internal __DEPRECATED_maxAllocationEpochs; /// @dev Rebate alpha numerator /// Originally used for Cobb-Douglas rebates, now used for exponential rebates - /// Deprecated, now applied on the SubgraphService + /// Deprecated, any rebate mechanism is now applied on the subgraph data service. uint32 internal __DEPRECATED_alphaNumerator; /// @dev Rebate alpha denominator /// Originally used for Cobb-Douglas rebates, now used for exponential rebates - /// Deprecated, now applied on the SubgraphService + /// Deprecated, any rebate mechanism is now applied on the subgraph data service. uint32 internal __DEPRECATED_alphaDenominator; - /// @dev Service provider stakes : serviceProviderAddress => ServiceProvider + /// @dev Service providers details, tracks stake utilization. mapping(address serviceProvider => IHorizonStakingTypes.ServiceProviderInternal details) internal _serviceProviders; - /// @dev Allocations : allocationID => Allocation - /// Deprecated, now applied on the SubgraphService + /// @dev Allocation details. + /// Deprecated, now applied on the subgraph data service mapping(address allocationId => IHorizonStakingExtension.Allocation allocation) internal __DEPRECATED_allocations; - /// @dev Subgraph Allocations: subgraphDeploymentID => tokens + /// @dev Subgraph allocations, tracks the tokens allocated to a subgraph deployment /// Deprecated, now applied on the SubgraphService mapping(bytes32 subgraphDeploymentId => uint256 tokens) internal __DEPRECATED_subgraphAllocations; - /// @dev Rebate pools : epoch => Pool - /// Deprecated. + /// @dev Rebate pool details per epoch + /// Deprecated with exponential rebates. mapping(uint256 epoch => uint256 rebates) private __DEPRECATED_rebates; // -- Slashing -- @@ -77,59 +80,66 @@ abstract contract HorizonStakingV1Storage { // -- Delegation -- /// @dev Delegation capacity multiplier defined by the delegation ratio - /// Deprecated, now applied by each data service as needed. + /// Deprecated, enforced by each data service as needed. uint32 internal __DEPRECATED_delegationRatio; - /// @dev Time in blocks an indexer needs to wait to change delegation parameters (deprecated) + /// @dev Time in blocks an indexer needs to wait to change delegation parameters + /// Deprecated, enforced by each data service as needed. uint32 internal __DEPRECATED_delegationParametersCooldown; /// @dev Time in epochs a delegator needs to wait to withdraw delegated stake /// Deprecated, now only enforced during a transition period - uint32 internal __DEPRECATED_delegationUnbondingPeriod; // in epochs + uint32 internal __DEPRECATED_delegationUnbondingPeriod; /// @dev Percentage of tokens to tax a delegation deposit /// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) /// Deprecated, no tax is applied now. uint32 internal __DEPRECATED_delegationTaxPercentage; - /// @dev Delegation pools : serviceProvider => DelegationPoolInternal - /// These are for the subgraph data service. + /// @dev Delegation pools (legacy). + /// Only used when the verifier is the subgraph data service. mapping(address serviceProvider => IHorizonStakingTypes.DelegationPoolInternal delegationPool) internal _legacyDelegationPools; // -- Operators -- - /// @dev Legacy operator auth : service provider => operator => is authorized + /// @dev Operator allow list (legacy) + /// Only used when the verifier is the subgraph data service. mapping(address legacyOperator => mapping(address serviceProvider => bool authorized)) internal _legacyOperatorAuth; // -- Asset Holders -- - /// @dev DEPRECATED: Allowed AssetHolders: assetHolder => is allowed + /// @dev Asset holder allow list + /// Deprecated with permissionless payers mapping(address assetHolder => bool allowed) private __DEPRECATED_assetHolders; - /// @dev Destination of accrued rewards : beneficiary => rewards destination + /// @dev Destination of accrued indexing rewards /// Deprecated, defined by each data service as needed mapping(address serviceProvider => address rewardsDestination) internal __DEPRECATED_rewardsDestination; /// @dev Address of the counterpart Staking contract on L1/L2 + /// Used for the transfer tools. address internal _counterpartStakingAddress; + /// @dev Address of the StakingExtension implementation + /// This is now an immutable variable to save some gas. address internal __DEPRECATED_extensionImpl; - // Additional rebate parameters for exponential rebates + // @dev Additional rebate parameters for exponential rebates + /// Deprecated, any rebate mechanism is now applied on the subgraph data service. uint32 internal __DEPRECATED_lambdaNumerator; uint32 internal __DEPRECATED_lambdaDenominator; - /// Maximum thawing period, in seconds, for a provision + // -- Horizon Staking -- + + /// @dev Maximum thawing period, in seconds, for a provision uint64 internal _maxThawingPeriod; /// @dev Provisions from each service provider for each data service - /// ServiceProvider => Verifier => Provision mapping(address serviceProvider => mapping(address verifier => IHorizonStakingTypes.Provision provision)) internal _provisions; /// @dev Delegation fee cuts for each service provider on each provision, by fee type: - /// ServiceProvider => Verifier => Payment Type => Fee Cut. /// This is the effective delegator fee cuts for each (data-service-defined) fee type (e.g. indexing fees, query fees). /// This is in PPM and is the cut taken by the service provider from the fees that correspond to delegators. /// (based on stake vs delegated stake proportion). @@ -137,22 +147,28 @@ abstract contract HorizonStakingV1Storage { mapping(address serviceProvider => mapping(address verifier => mapping(IGraphPayments.PaymentTypes paymentType => uint256 feeCut))) internal _delegationFeeCut; + /// @dev Thaw requests + /// Details for each thawing operation in the staking contract (for both service providers and delegators). mapping(bytes32 thawRequestId => IHorizonStakingTypes.ThawRequest thawRequest) internal _thawRequests; + /// @dev Thaw request lists + /// Metadata defining linked lists of thaw requests for each service provider or delegator (owner) mapping(address serviceProvider => mapping(address verifier => mapping(address owner => LinkedList.List list))) internal _thawRequestLists; - // service provider => verifier => operator => authorized + /// @dev Operator allow list + /// Used for all verifiers except the subgraph data service. mapping(address serviceProvider => mapping(address verifier => mapping(address operator => bool authorized))) internal _operatorAuth; - // governance enables or disables delegation slashing with this flag + /// @dev Flag to enable or disable delegation slashing bool internal _delegationSlashingEnabled; - // delegation pools for each service provider and verifier + /// @dev Delegation pools for each service provider and verifier mapping(address serviceProvider => mapping(address verifier => IHorizonStakingTypes.DelegationPoolInternal delegationPool)) internal _delegationPools; - // allowed verifiers for locked provisions (i.e. from GraphTokenLockWallets) + /// @dev Allowed verifiers for locked provisions (i.e. from GraphTokenLockWallets) + // Verifiers are whitelisted to ensure locked tokens cannot escape using an arbitrary verifier. mapping(address verifier => bool allowed) internal _allowedLockedVerifiers; } diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index d9cbc9980..5f5a0f6b3 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -10,21 +10,35 @@ import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; /** * @title Graph Managed contract * @dev The Managed contract provides an interface to interact with the Controller. - * Inspired by Livepeer: - * https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol + * For Graph Horizon this contract is mostly a shell that uses {GraphDirectory}, however since the {HorizonStaking} + * contract uses it we need to preserve the storage layout. + * Inspired by Livepeer: https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol */ abstract contract Managed is GraphDirectory { // -- State -- /// Controller that manages this contract address private __DEPRECATED_controller; + /// @dev Cache for the addresses of the contracts retrieved from the controller mapping(bytes32 contractName => address contractAddress) private __DEPRECATED_addressCache; + /// @dev Gap for future storage variables uint256[10] private __gap; + /** + * @notice Thrown when a protected function is called and the contract is paused. + */ error ManagedIsPaused(); + + /** + * @notice Thrown when a the caller is not the expected controller address. + */ error ManagedOnlyController(); + + /** + * @notice Thrown when a the caller is not the governor. + */ error ManagedOnlyGovernor(); /** @@ -51,5 +65,9 @@ abstract contract Managed is GraphDirectory { _; } + /** + * @dev Initialize the contract + * @param controller_ The address of the Graph controller contract. + */ constructor(address controller_) GraphDirectory(controller_) {} } From 75d3cb9ebd95f69cdac83392bd55666b361ae362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 29 May 2024 17:56:42 -0300 Subject: [PATCH 089/277] docs: add natspec to data service fees extension contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 2 +- .../contracts/data-service/GraphDirectory.sol | 95 ++++++++++++++++++- .../extensions/DataServiceFees.sol | 55 ++++++++++- .../data-service/interfaces/IDataService.sol | 9 +- .../interfaces/IDataServiceFees.sol | 64 ++++++++++++- .../internal/IHorizonStakingTypes.sol | 3 +- .../contracts/staking/HorizonStaking.sol | 5 +- .../contracts/staking/HorizonStakingBase.sol | 1 + 8 files changed, 211 insertions(+), 23 deletions(-) diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index 681d13f73..ded9378fa 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -13,7 +13,7 @@ import { ProvisionManager } from "./utilities/ProvisionManager.sol"; * - GraphDirectory, allows the data service to interact with Graph Horizon contracts * - ProvisionManager, provides functionality to manage provisions * - * The derived contract should add functionality that implements the interfaces described in {IDataService}. + * The derived contract MUST implement all the interfaces described in {IDataService}. */ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1Storage, IDataService { /** diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index a59200982..ffa1c08ad 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -24,24 +24,59 @@ import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration * and uses immutable variables to minimize gas costs. */ abstract contract GraphDirectory { - // Graph Horizon contracts + // -- Graph Horizon contracts -- + + /// @dev The Graph Token contract address IGraphToken private immutable GRAPH_TOKEN; + + /// @dev The Horizon Staking contract address IHorizonStaking private immutable GRAPH_STAKING; + + /// @dev The Graph Payments contract address IGraphPayments private immutable GRAPH_PAYMENTS; + + /// @dev The Payments Escrow contract address IPaymentsEscrow private immutable GRAPH_PAYMENTS_ESCROW; - // Graph periphery contracts + // -- Graph periphery contracts -- + + /// @dev The Graph Controller contract address IController private immutable GRAPH_CONTROLLER; + + /// @dev The Epoch Manager contract address IEpochManager private immutable GRAPH_EPOCH_MANAGER; + + /// @dev The Rewards Manager contract address IRewardsManager private immutable GRAPH_REWARDS_MANAGER; + + /// @dev The Token Gateway contract address ITokenGateway private immutable GRAPH_TOKEN_GATEWAY; + + /// @dev The Bridge Escrow contract address IBridgeEscrow private immutable GRAPH_BRIDGE_ESCROW; + + /// @dev The Graph Proxy Admin contract address IGraphProxyAdmin private immutable GRAPH_PROXY_ADMIN; - // Legacy Graph contracts - required for StakingBackwardCompatibility - // TODO: remove these once StakingBackwardCompatibility is removed + // -- Legacy Graph contracts -- + // These are required for backwards compatibility on HorizonStakingExtension + // TODO: remove these once HorizonStakingExtension is removed ICuration private immutable GRAPH_CURATION; + /** + * @notice Emitted when the GraphDirectory is initialized + * @param graphToken The Graph Token contract address + * @param graphStaking The Horizon Staking contract address + * @param graphPayments The Graph Payments contract address + * @param graphEscrow The Payments Escrow contract address + * @param graphController The Graph Controller contract address + * @param graphEpochManager The Epoch Manager contract address + * @param graphRewardsManager The Rewards Manager contract address + * @param graphTokenGateway The Token Gateway contract address + * @param graphBridgeEscrow The Bridge Escrow contract address + * @param graphProxyAdmin The Graph Proxy Admin contract address + * @param graphCuration The Curation contract address + */ event GraphDirectoryInitialized( IGraphToken indexed graphToken, IHorizonStaking indexed graphStaking, @@ -56,8 +91,21 @@ abstract contract GraphDirectory { ICuration graphCuration ); + /** + * @notice Thrown when either the controller is the zero address or a contract address is not found + * on the controller + * @param contractName The name of the contract that was not found, or the controller + */ error GraphDirectoryInvalidZeroAddress(bytes contractName); + /** + * @notice Constructor for the GraphDirectory contract + * @dev Requirements: + * - `controller` cannot be zero address + * + * Emits a {GraphDirectoryInitialized} event + * @param controller The address of the Graph Controller contract. + */ constructor(address controller) { require(controller != address(0), GraphDirectoryInvalidZeroAddress("Controller")); @@ -88,50 +136,89 @@ abstract contract GraphDirectory { ); } + /** + * @notice Get the Graph Token contract + */ function _graphToken() internal view returns (IGraphToken) { return GRAPH_TOKEN; } + /** + * @notice Get the Horizon Staking contract + */ function _graphStaking() internal view returns (IHorizonStaking) { return GRAPH_STAKING; } + /** + * @notice Get the Graph Payments contract + */ function _graphPayments() internal view returns (IGraphPayments) { return GRAPH_PAYMENTS; } + /** + * @notice Get the Payments Escrow contract + */ function _graphPaymentsEscrow() internal view returns (IPaymentsEscrow) { return GRAPH_PAYMENTS_ESCROW; } + /** + * @notice Get the Graph Controller contract + */ function _graphController() internal view returns (IController) { return GRAPH_CONTROLLER; } + /** + * @notice Get the Epoch Manager contract + */ function _graphEpochManager() internal view returns (IEpochManager) { return GRAPH_EPOCH_MANAGER; } + /** + * @notice Get the Rewards Manager contract + */ function _graphRewardsManager() internal view returns (IRewardsManager) { return GRAPH_REWARDS_MANAGER; } + /** + * @notice Get the Graph Token Gateway contract + */ function _graphTokenGateway() internal view returns (ITokenGateway) { return GRAPH_TOKEN_GATEWAY; } + /** + * @notice Get the Bridge Escrow contract + */ function _graphBridgeEscrow() internal view returns (IBridgeEscrow) { return GRAPH_BRIDGE_ESCROW; } + /** + * @notice Get the Graph Proxy Admin contract + */ function _graphProxyAdmin() internal view returns (IGraphProxyAdmin) { return GRAPH_PROXY_ADMIN; } + /** + * @notice Get the Curation contract + */ function _graphCuration() internal view returns (ICuration) { return GRAPH_CURATION; } + /** + * @notice Get a contract address from the controller + * @dev Requirements: + * - The `_contractName` must be registered in the controller + * @param _contractName The name of the contract to fetch from the controller + */ function _getContractFromController(bytes memory _contractName) private view returns (address) { address contractAddress = GRAPH_CONTROLLER.getContractProxy(keccak256(_contractName)); require(contractAddress != address(0), GraphDirectoryInvalidZeroAddress(_contractName)); diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index b8602eb2a..c4a203942 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -9,14 +9,35 @@ import { LinkedList } from "../../libraries/LinkedList.sol"; import { DataService } from "../DataService.sol"; import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol"; +/** + * @title DataServiceFees + * @notice Adds functionality to the {IDataService} contract to handle payment collateralization + * using a Horizon provision. See {IDataServiceFees} for more details. + * @dev Implementation of the {IDataServiceFees} interface. + */ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDataServiceFees { using ProvisionTracker for mapping(address => uint256); using LinkedList for LinkedList.List; + /** + * @notice See {IDataServiceFees-releaseStake} + */ function releaseStake(uint256 n) external virtual { _releaseStake(msg.sender, n); } + /** + * @notice Locks stake for a service provider to back a payment. + * Creates a stake claim, which is stored in a linked list by service provider. + * @dev Requirements: + * - The associated provision must have enough available tokens to lock the stake. + * + * Emits a {StakeClaimLocked} event. + * + * @param _serviceProvider The address of the service provider + * @param _tokens The amount of tokens to lock in the claim + * @param _unlockTimestamp The timestamp when the tokens can be released + */ function _lockStake(address _serviceProvider, uint256 _tokens, uint256 _unlockTimestamp) internal { feesProvisionTracker.lock(_graphStaking(), _serviceProvider, _tokens, maximumDelegationRatio); @@ -25,7 +46,6 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat // Save item and add to list bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); claims[claimId] = StakeClaim({ - serviceProvider: _serviceProvider, tokens: _tokens, createdAt: block.timestamp, releaseAt: _unlockTimestamp, @@ -37,8 +57,9 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat emit StakeClaimLocked(_serviceProvider, claimId, _tokens, _unlockTimestamp); } - /// @notice Release expired stake claims for a service provider - /// @param _n The number of stake claims to release, or 0 to release all + /** + * @notice See {IDataServiceFees-releaseStake} + */ function _releaseStake(address _serviceProvider, uint256 _n) internal { LinkedList.List storage claimsList = claimsLists[_serviceProvider]; (uint256 claimsReleased, bytes memory data) = claimsList.traverse( @@ -52,6 +73,15 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat emit StakeClaimsReleased(_serviceProvider, claimsReleased, abi.decode(data, (uint256))); } + /** + * @notice Processes a stake claim, releasing the tokens if the claim has expired. + * @dev This function is used as a callback in the stake claims linked list traversal. + * @param _claimId The id of the stake claim + * @param _acc The accumulator for the stake claims being processed + * @return Wether the stake claim is still locked, indicating that the traversal should continue or stop. + * @return Wether the stake claim should be deleted + * @return The updated accumulator data + */ function _processStakeClaim(bytes32 _claimId, bytes memory _acc) private returns (bool, bool, bytes memory) { StakeClaim memory claim = _getStakeClaim(_claimId); @@ -72,22 +102,41 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat return (false, true, _acc); } + /** + * @notice Deletes a stake claim. + * @dev This function is used as a callback in the stake claims linked list traversal. + * @param _claimId The ID of the stake claim to delete + */ function _deleteStakeClaim(bytes32 _claimId) private { delete claims[_claimId]; } + /** + * @notice Gets the details of a stake claim + * @param _claimId The ID of the stake claim + */ function _getStakeClaim(bytes32 _claimId) private view returns (StakeClaim memory) { StakeClaim memory claim = claims[_claimId]; require(claim.createdAt != 0, DataServiceFeesClaimNotFound(_claimId)); return claim; } + /** + * @notice Gets the next stake claim in the linked list + * @dev This function is used as a callback in the stake claims linked list traversal. + * @param _claimId The ID of the stake claim + */ function _getNextStakeClaim(bytes32 _claimId) private view returns (bytes32) { StakeClaim memory claim = claims[_claimId]; require(claim.createdAt != 0, DataServiceFeesClaimNotFound(_claimId)); return claim.nextClaim; } + /** + * @notice Builds a stake claim ID + * @param _serviceProvider The address of the service provider + * @param _nonce A nonce of the stake claim + */ function _buildStakeClaimId(address _serviceProvider, uint256 _nonce) private view returns (bytes32) { return keccak256(abi.encodePacked(address(this), _serviceProvider, _nonce)); } diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index 6814ef23e..a30fb3b90 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -5,18 +5,13 @@ import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; /** * @title Interface of the base {DataService} contract as defined by the Graph Horizon specification. - * @dev This interface provides a guardrail for data service implementations that utilize Graph Horizon. + * @notice This interface provides a guardrail for data service implementations that utilize Graph Horizon. * It's expected that implementations follow the specification however much of it is intentionally loose * to allow for greater flexibility when designing a data service. For specifics always check the data * service implementation. * In general, this is a great starting point for data services that want to use Graph Horizon - * to provide economic security for a service being provided. It assumes two main forms of retribution for - * service providers: - * - service payment, to compensate ongoing work required to serve customers requests - * - service fees, earnt by serving customer requests, ideally leveraging {GraphPayments} to collect fees from the payer - * - * TIP: TODO: link to data service framework documentation + * to provide economic security for a service being provided. */ interface IDataService { /** diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index cab7e9998..3cb63a50b 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -3,34 +3,88 @@ pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; +/** + * @title Interface for the {IDataServiceFees} contract. + * @notice Adds functionality to the {IDataService} contract to handle payment collateralization + * using a Horizon provision. + * + * It's designed to be used with the Data Service framework: + * - When a service provider collects payment with {IDataService.collect} the data service should lock + * stake to back the payment using {_lockStake}. + * - Every time there is a payment collection with {IDataService.collect}, the data service should + * attempt to release any expired stake claims by calling {_releaseStake}. + * - Stake claims can also be manually released by calling {releaseStake} directly. + * + * @dev Note that this implementation uses the entire provisioned stake as collateral for the payment. + * It can be used to provide economic security for the payments collected as long as the provisioned + * stake is not being used for other purposes. + */ interface IDataServiceFees is IDataService { - /// A locked stake claim to be released to a service provider + /** + * @notice A stake claim, representing provisioned stake that gets locked + * to be released to a service provider. + * @dev StakeClaims are stored in linked lists by service provider, ordered by + * creation timestamp. + */ struct StakeClaim { - address serviceProvider; - // tokens to be released with this claim + // The amount of tokens to be locked in the claim uint256 tokens; + // Timestamp when the claim was created uint256 createdAt; - // timestamp when the claim can be released + // Timestamp when the claim will expire and tokens can be released uint256 releaseAt; - // next claim in the linked list + // Next claim in the linked list bytes32 nextClaim; } + /** + * @notice Emitted when a stake claim is created and stake is locked. + * @param serviceProvider The address of the service provider + * @param claimId The id of the stake claim + * @param tokens The amount of tokens to lock in the claim + * @param unlockTimestamp The timestamp when the tokens can be released + */ event StakeClaimLocked( address indexed serviceProvider, bytes32 indexed claimId, uint256 tokens, uint256 unlockTimestamp ); + + /** + * @notice Emitted when a stake claim is released and stake is unlocked. + * @param serviceProvider The address of the service provider + * @param claimId The id of the stake claim + * @param tokens The amount of tokens released + * @param releaseAt The timestamp when the tokens were released + */ event StakeClaimReleased( address indexed serviceProvider, bytes32 indexed claimId, uint256 tokens, uint256 releaseAt ); + + /** + * @notice Emitted when a series of stake claims are released. + * @param serviceProvider The address of the service provider + * @param claimsCount The number of stake claims being released + * @param tokensReleased The total amount of tokens being released + */ event StakeClaimsReleased(address indexed serviceProvider, uint256 claimsCount, uint256 tokensReleased); + /** + * @notice Thrown when attempting to get a stake claim that does not exist. + */ error DataServiceFeesClaimNotFound(bytes32 claimId); + /** + * @notice Releases expired stake claims for the caller. + * @dev This function is only meant to be called if the service provider has enough + * stake claims that releasing them all at once would exceed the block gas limit. + * @dev This function can be overriden and/or disabled. + * @dev Emits a {StakeClaimsReleased} event, and a {StakeClaimReleased} event for each claim released. + * @param n Amount of stake claims to process. If 0, all stake claims are processed. + */ function releaseStake(uint256 n) external; } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index ae2a05516..c0d6892b3 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -127,7 +127,8 @@ interface IHorizonStakingTypes { /** * @notice Details of a stake thawing operation. - * @dev ThawRequests are stored in linked lists by service provider/delegator. + * @dev ThawRequests are stored in linked lists by service provider/delegator, + * ordered by creation timestamp. */ struct ThawRequest { // Shares that represent the tokens being thawed diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index f1c0a7f3c..ca3786975 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -877,11 +877,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice Fulfills a thaw request. - * @dev This function is used as a callback in the linked list traversal. + * @dev This function is used as a callback in the thaw requests linked list traversal. * * Emits a {ThawRequestFulfilled} event. * * @param _thawRequestId The ID of the current thaw request + * @param _acc The accumulator data for the thaw requests being fulfilled * @return Wether the thaw request is still thawing, indicating that the traversal should continue or stop. * @return Wether the thaw request should be deleted * @return The updated accumulator data @@ -914,7 +915,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice Deletes a ThawRequest. - * @dev This function is used as a callback in the linked list traversal. + * @dev This function is used as a callback in the thaw requests linked list traversal. * @param _thawRequestId The ID of the thaw request to delete */ function _deleteThawRequest(bytes32 _thawRequestId) private { diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index c173c4bec..c3eca6b43 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -284,6 +284,7 @@ abstract contract HorizonStakingBase is /** * @notice Gets the next thaw request after `_thawRequestId`. + * @dev This function is used as a callback in the thaw requests linked list traversal. */ function _getNextThawRequest(bytes32 _thawRequestId) internal view returns (bytes32) { return _thawRequests[_thawRequestId].next; From 8616335633dee3ea047982e61ce27d6aba285bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 30 May 2024 13:30:13 -0300 Subject: [PATCH 090/277] docs: add natspec to data service contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 24 +- .../extensions/DataServiceFees.sol | 6 +- .../extensions/DataServiceFeesStorage.sol | 3 + .../extensions/DataServicePausable.sol | 28 ++ .../DataServicePausableUpgradeable.sol | 34 ++- .../extensions/DataServiceRescuable.sol | 31 +- .../data-service/interfaces/IDataService.sol | 14 +- .../interfaces/IDataServiceFees.sol | 4 +- .../interfaces/IDataServicePausable.sol | 31 ++ .../interfaces/IDataServiceRescuable.sol | 42 ++- .../libraries/ProvisionTracker.sol | 40 ++- .../utilities/ProvisionManager.sol | 276 +++++++++++++++--- .../utilities/ProvisionManagerStorage.sol | 3 + .../staking/libraries/ExponentialRebates.sol | 2 +- .../contracts/SubgraphService.sol | 1 + .../contracts/utilities/AllocationManager.sol | 4 +- .../utilities/AttestationManager.sol | 7 +- 17 files changed, 462 insertions(+), 88 deletions(-) diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index ded9378fa..d9f2ec1e5 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -8,12 +8,16 @@ import { GraphDirectory } from "./GraphDirectory.sol"; import { ProvisionManager } from "./utilities/ProvisionManager.sol"; /** - * @title Implementation of the {IDataService} interface. - * @dev This implementation provides base functionality for a data service: + * @title DataService contract + * @dev Implementation of the {IDataService} interface. + * @notice This implementation provides base functionality for a data service: * - GraphDirectory, allows the data service to interact with Graph Horizon contracts * - ProvisionManager, provides functionality to manage provisions * - * The derived contract MUST implement all the interfaces described in {IDataService}. + * The derived contract MUST implement all the interfaces described in {IDataService} and in + * accordance with the Data Service framework. + * @dev Implementation must initialize the contract using {__DataService_init} or + * {__DataService_init_unchained} functions. */ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1Storage, IDataService { /** @@ -21,4 +25,18 @@ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1 * @param controller The address of the Graph Horizon controller contract. */ constructor(address controller) GraphDirectory(controller) {} + + /** + * @notice Initializes the contract and any parent contracts. + */ + function __DataService_init() internal onlyInitializing { + __DataService_init_unchained(); + } + + /** + * @notice Initializes the contract. + */ + function __DataService_init_unchained() internal onlyInitializing { + __ProvisionManager_init_unchained(); + } } diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index c4a203942..000a72d09 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -10,10 +10,10 @@ import { DataService } from "../DataService.sol"; import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol"; /** - * @title DataServiceFees - * @notice Adds functionality to the {IDataService} contract to handle payment collateralization - * using a Horizon provision. See {IDataServiceFees} for more details. + * @title DataServiceFees contract * @dev Implementation of the {IDataServiceFees} interface. + * @notice Extension for the {IDataService} contract to handle payment collateralization + * using a Horizon provision. See {IDataServiceFees} for more details. */ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDataServiceFees { using ProvisionTracker for mapping(address => uint256); diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 57e178e86..483b67b80 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -5,6 +5,9 @@ import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; import { LinkedList } from "../../libraries/LinkedList.sol"; +/** + * @title Storage layout for the {DataServiceFees} extension contract. + */ abstract contract DataServiceFeesV1Storage { mapping(address serviceProvider => uint256 tokens) public feesProvisionTracker; diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index df8c1c402..577db9677 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -6,22 +6,50 @@ import { IDataServicePausable } from "../interfaces/IDataServicePausable.sol"; import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; import { DataService } from "../DataService.sol"; +/** + * @title DataServicePausable contract + * @dev Implementation of the {IDataServicePausable} interface. + * @notice Extension for the {IDataService} contract, adds pausing functionality + * to the data service. Pausing is controlled by privileged accounts called + * pause guardians. + * @dev Note that this extension does not provide an external function to set pause + * guardians. This should be implemented in the derived contract. + */ abstract contract DataServicePausable is Pausable, DataService, IDataServicePausable { + /// @notice List of pause guardians and their allowed status mapping(address pauseGuardian => bool allowed) public pauseGuardians; + /** + * @notice Checks if the caller is a pause guardian. + */ modifier onlyPauseGuardian() { require(pauseGuardians[msg.sender], DataServicePausableNotPauseGuardian(msg.sender)); _; } + /** + * @notice See {IDataServicePausable-pause} + */ function pause() external onlyPauseGuardian whenNotPaused { _pause(); } + /** + * @notice See {IDataServicePausable-pause} + */ function unpause() external onlyPauseGuardian whenPaused { _unpause(); } + /** + * @notice Sets a pause guardian. + * @dev Internal function to be used by the derived contract to set pause guardians. + * + * Emits a {PauseGuardianSet} event. + * + * @param _pauseGuardian The address of the pause guardian + * @param _allowed The allowed status of the pause guardian + */ function _setPauseGuardian(address _pauseGuardian, bool _allowed) internal whenNotPaused { pauseGuardians[_pauseGuardian] = _allowed; emit PauseGuardianSet(_pauseGuardian, _allowed); diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol index a57087e0e..53003ebfc 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol @@ -6,31 +6,61 @@ import { IDataServicePausable } from "../interfaces/IDataServicePausable.sol"; import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; import { DataService } from "../DataService.sol"; +/** + * @title DataServicePausableUpgradeable contract + * @dev Implementation of the {IDataServicePausable} interface. + * @dev Upgradeable version of the {DataServicePausable} contract. + */ abstract contract DataServicePausableUpgradeable is PausableUpgradeable, DataService, IDataServicePausable { + /// @notice List of pause guardians and their allowed status mapping(address pauseGuardian => bool allowed) public pauseGuardians; + /** + * @notice Checks if the caller is a pause guardian. + */ modifier onlyPauseGuardian() { require(pauseGuardians[msg.sender], DataServicePausableNotPauseGuardian(msg.sender)); _; } + /** + * @notice See {IDataServicePausable-pause} + */ function pause() external onlyPauseGuardian whenNotPaused { _pause(); } + /** + * @notice See {IDataServicePausable-pause} + */ function unpause() external onlyPauseGuardian whenPaused { _unpause(); } + /** + * @notice Initializes the contract and parent contracts + */ // solhint-disable-next-line func-name-mixedcase - function __DataServicePausable_init() internal { + function __DataServicePausable_init() internal onlyInitializing { __Pausable_init_unchained(); __DataServicePausable_init_unchained(); } + /** + * @notice Initializes the contract + */ // solhint-disable-next-line func-name-mixedcase - function __DataServicePausable_init_unchained() internal {} + function __DataServicePausable_init_unchained() internal onlyInitializing {} + /** + * @notice Sets a pause guardian. + * @dev Internal function to be used by the derived contract to set pause guardians. + * + * Emits a {PauseGuardianSet} event. + * + * @param _pauseGuardian The address of the pause guardian + * @param _allowed The allowed status of the pause guardian + */ function _setPauseGuardian(address _pauseGuardian, bool _allowed) internal whenNotPaused { pauseGuardians[_pauseGuardian] = _allowed; emit PauseGuardianSet(_pauseGuardian, _allowed); diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 3fc23422d..f321b8d22 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -14,23 +14,44 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s * @dev Allows a contract to have a function to rescue tokens sent by mistake. * The contract must implement the external rescueTokens function or similar, * that calls this contract's _rescueTokens. + * @dev Note that this extension does not provide an external function to set + * rescuers. This should be implemented in the derived contract. */ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { + /// @notice List of rescuers and their allowed status mapping(address rescuer => bool allowed) public rescuers; + /** + * @notice Checks if the caller is a rescuer. + */ modifier onlyRescuer() { require(rescuers[msg.sender], DataServiceRescuableNotRescuer(msg.sender)); _; } - function rescueGRT(address to, uint256 tokens) external onlyRescuer { + /** + * @notice See {IDataServiceRescuable-rescueGRT} + */ + function rescueGRT(address to, uint256 tokens) external virtual onlyRescuer { _rescueTokens(to, address(_graphToken()), tokens); } - function rescueETH(address payable to, uint256 tokens) external onlyRescuer { + /** + * @notice See {IDataServiceRescuable-rescueETH} + */ + function rescueETH(address payable to, uint256 tokens) external virtual onlyRescuer { _rescueTokens(to, Denominations.NATIVE_TOKEN, tokens); } + /** + * @notice Sets a rescuer. + * @dev Internal function to be used by the derived contract to set rescuers. + * + * Emits a {RescuerSet} event. + * + * @param _rescuer Address of the rescuer + * @param _allowed Allowed status of the rescuer + */ function _setRescuer(address _rescuer, bool _allowed) internal { rescuers[_rescuer] = _allowed; emit RescuerSet(_rescuer, _allowed); @@ -38,9 +59,9 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { /** * @dev Allows rescuing tokens sent to this contract - * @param _to Destination address to send the tokens - * @param _token Address of the token being rescued - * @param _tokens Amount of tokens to pull + * @param _to Destination address to send the tokens + * @param _token Address of the token being rescued + * @param _tokens Amount of tokens to pull */ function _rescueTokens(address _to, address _token, uint256 _tokens) internal { require(_tokens != 0, DataServiceRescuableCannotRescueZero()); diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index a30fb3b90..aa3ef3dfa 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -5,13 +5,13 @@ import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; /** * @title Interface of the base {DataService} contract as defined by the Graph Horizon specification. - * @notice This interface provides a guardrail for data service implementations that utilize Graph Horizon. - * It's expected that implementations follow the specification however much of it is intentionally loose - * to allow for greater flexibility when designing a data service. For specifics always check the data - * service implementation. - - * In general, this is a great starting point for data services that want to use Graph Horizon - * to provide economic security for a service being provided. + * @notice This interface provides a guardrail for contracts that use the Data Service framework + * to implement a data service on Graph Horizon. Much of the specification is intentionally loose + * to allow for greater flexibility when designing a data service. It's not possible to guarantee that + * an implementation will honor the Data Service framework guidelines so it's advised to always review + * the implementation code and the documentation. + * @dev This interface is expected to be inherited and extended by a data service interface. It can be + * used to interact with it however it's advised to use the more specific parent interface. */ interface IDataService { /** diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index 3cb63a50b..b730a09e6 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; /** - * @title Interface for the {IDataServiceFees} contract. - * @notice Adds functionality to the {IDataService} contract to handle payment collateralization + * @title Interface for the {DataServiceFees} contract. + * @notice Extension for the {IDataService} contract to handle payment collateralization * using a Horizon provision. * * It's designed to be used with the Data Service framework: diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol index 673238b7f..04e931749 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol @@ -3,12 +3,43 @@ pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; +/** + * @title Interface for the {DataServicePausable} contract. + * @notice Extension for the {IDataService} contract, adds pausing functionality + * to the data service. Pausing is controlled by privileged accounts called + * pause guardians. + */ interface IDataServicePausable is IDataService { + /** + * @notice Emitted when a pause guardian is set. + * @param account The address of the pause guardian + * @param allowed The allowed status of the pause guardian + */ event PauseGuardianSet(address indexed account, bool allowed); + /** + * @notice Emitted when a the caller is not a pause guardian + * @param account The address of the pause guardian + */ error DataServicePausableNotPauseGuardian(address account); + /** + * @notice Pauses the data service. + * @dev Note that only functions using the modifiers `whenNotPaused` + * and `whenPaused` will be affected by the pause. + * + * Requirements: + * - The contract must not be already paused + */ function pause() external; + /** + * @notice Unpauses the data service. + * @dev Note that only functions using the modifiers `whenNotPaused` + * and `whenPaused` will be affected by the pause. + * + * Requirements: + * - The contract must be paused + */ function unpause() external; } diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index f1494413f..ba21f3019 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -3,17 +3,57 @@ pragma solidity 0.8.26; import { IDataService } from "./IDataService.sol"; +/** + * @title Interface for the {IDataServicePausable} contract. + * @notice Extension for the {IDataService} contract, adds the ability to rescue + * any ERC20 token or ETH from the contract, controlled by a rescuer privileged role. + */ interface IDataServiceRescuable is IDataService { /** - * @dev Tokens rescued by the user + * @notice Emitted when tokens are rescued from the contract. */ event TokensRescued(address indexed from, address indexed to, uint256 tokens); + + /** + * @notice Emitted when a rescuer is set. + */ event RescuerSet(address indexed account, bool allowed); + /** + * @notice Thrown when trying to rescue zero tokens. + */ error DataServiceRescuableCannotRescueZero(); + + /** + * @notice Thrown when the caller is not a rescuer. + */ error DataServiceRescuableNotRescuer(address account); + /** + * @notice Rescues GRT tokens from the contract. + * @dev Declared as virtual to allow disabling the function via override. + * + * Requirements: + * - Cannot rescue zero tokens. + * + * Emits a {TokensRescued} event. + * + * @param to Address of the tokens recipient. + * @param tokens Amount of tokens to rescue. + */ function rescueGRT(address to, uint256 tokens) external; + /** + * @notice Rescues ether from the contract. + * @dev Declared as virtual to allow disabling the function via override. + * + * Requirements: + * - Cannot rescue zeroether. + * + * Emits a {TokensRescued} event. + * + * @param to Address of the tokens recipient. + * @param tokens Amount of tokens to rescue. + */ function rescueETH(address payable to, uint256 tokens) external; } diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index 4358b33b2..a95f634f8 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -3,9 +3,30 @@ pragma solidity 0.8.26; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; +/** + * @title ProvisionTracker library + * @notice A library to facilitate tracking of "used tokens" on Graph Horizon provisions. This can be used to + * ensure data services have enough economic security (provisioned stake) to back the payments they collect for + * their services. + * The library provides two primitives, lock and release to signal token usage and free up tokens respectively. It + * does not make any assumptions about the conditions under which tokens are locked or released. + */ library ProvisionTracker { + /** + * @notice Thrown when trying to lock more tokens than available + */ error ProvisionTrackerInsufficientTokens(uint256 tokensAvailable, uint256 tokensRequired); + /** + * @notice Locks tokens for a service provider + * @dev Requirements: + * - `tokens` must be less than or equal to the amount of tokens available, as reported by the HorizonStaking contract + * @param self The provision tracker mapping + * @param graphStaking The HorizonStaking contract + * @param serviceProvider The service provider address + * @param tokens The amount of tokens to lock + * @param delegationRatio A delegation ratio to limit the amount of delegation that's usable + */ function lock( mapping(address => uint256) storage self, IHorizonStaking graphStaking, @@ -21,20 +42,17 @@ library ProvisionTracker { self[serviceProvider] += tokens; } + /** + * @notice Releases tokens for a service provider + * @dev Requirements: + * - `tokens` must be less than or equal to the amount of tokens locked for the service provider + * @param self The provision tracker mapping + * @param serviceProvider The service provider address + * @param tokens The amount of tokens to release + */ function release(mapping(address => uint256) storage self, address serviceProvider, uint256 tokens) internal { if (tokens == 0) return; require(self[serviceProvider] >= tokens, ProvisionTrackerInsufficientTokens(self[serviceProvider], tokens)); self[serviceProvider] -= tokens; } - - function getTokensFree( - mapping(address => uint256) storage self, - IHorizonStaking graphStaking, - address serviceProvider, - uint32 delegationRatio - ) internal view returns (uint256) { - uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this), delegationRatio); - if (tokensAvailable >= self[serviceProvider]) return tokensAvailable - self[serviceProvider]; - else return 0; - } } diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index c09a17ada..ff02978fb 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -5,48 +5,118 @@ import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; import { UintRange } from "../../libraries/UintRange.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { GraphDirectory } from "../GraphDirectory.sol"; import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; -abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage { +/** + * @title ProvisionManager contract + * @notice A helper contract that implements several provision management functions. + * @dev Provides utilities to verify provision parameters are within an acceptable range. Each + * parameter has an overridable setter and getter for the validity range, and a checker that reverts + * if the parameter is out of range. + * The parameters are: + * - Provision parameters (thawing period and verifier cut) + * - Delegation ratio + * - Provision tokens + */ +abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionManagerV1Storage { using UintRange for uint256; + /** + * @notice Emitted when the provision tokens range is set. + * @param min The minimum allowed value for the provision tokens. + * @param max The maximum allowed value for the provision tokens. + */ + event ProvisionTokensRangeSet(uint256 min, uint256 max); + + /** + * @notice Emitted when the delegation ratio range is set. + * @param min The minimum allowed value for the delegation ratio. + * @param max The maximum allowed value for the delegation ratio. + */ + event DelegationRatioRangeSet(uint32 min, uint32 max); + + /** + * @notice Emitted when the verifier cut range is set. + * @param min The minimum allowed value for the max verifier cut. + * @param max The maximum allowed value for the max verifier cut. + */ + event VerifierCutRangeSet(uint32 min, uint32 max); + + /** + * @notice Emitted when the thawing period range is set. + * @param min The minimum allowed value for the thawing period. + * @param max The maximum allowed value for the thawing period. + */ + event ThawingPeriodRangeSet(uint64 min, uint64 max); + + /** + * @notice Thrown when a provision parameter is out of range. + * @param message The error message. + * @param value The value that is out of range. + * @param min The minimum allowed value. + * @param max The maximum allowed value. + */ error ProvisionManagerInvalidValue(bytes message, uint256 value, uint256 min, uint256 max); - error ProvisionManagerNotAuthorized(address caller, address serviceProvider, address service); - error ProvisionManagerProvisionNotFound(address serviceProvider, address service); + /** + * @notice Thrown when the caller is not authorized to manage the provision of a service provider. + * @param caller The address of the caller. + * @param serviceProvider The address of the service provider. + */ + error ProvisionManagerNotAuthorized(address caller, address serviceProvider); + + /** + * @notice Thrown when a provision is not found. + * @param serviceProvider The address of the service provider. + */ + error ProvisionManagerProvisionNotFound(address serviceProvider); + + /** + * @notice Checks if the caller is authorized to manage the provision of a service provider. + */ modifier onlyProvisionAuthorized(address serviceProvider) { require( _graphStaking().isAuthorized(msg.sender, serviceProvider, address(this)), - ProvisionManagerNotAuthorized(msg.sender, serviceProvider, address(this)) + ProvisionManagerNotAuthorized(msg.sender, serviceProvider) ); _; } + /** + * @notice Checks if a provision of a service provider is valid according + * to the parameter ranges established. + */ modifier onlyValidProvision(address serviceProvider) virtual { - _checkProvisionTokens(serviceProvider); - _checkProvisionDelegationRatio(serviceProvider); - _checkProvisionParameters(serviceProvider, false); + IHorizonStaking.Provision memory provision = _getProvision(serviceProvider); + _checkProvisionTokens(provision); + _checkProvisionDelegationRatio(provision, serviceProvider); + _checkProvisionParameters(provision, false); _; } - constructor() { - minimumProvisionTokens = type(uint256).min; - maximumProvisionTokens = type(uint256).max; - - minimumDelegationRatio = type(uint32).min; - maximumDelegationRatio = type(uint32).max; - - minimumThawingPeriod = type(uint64).min; - maximumThawingPeriod = type(uint64).max; + /** + * @notice Initializes the contract and any parent contracts. + */ + function __ProvisionManager_init() internal onlyInitializing { + __ProvisionManager_init_unchained(); + } - minimumVerifierCut = type(uint32).min; - maximumVerifierCut = type(uint32).max; + /** + * @notice Initializes the contract. + * @dev All parameters set to their entire range as valid. + */ + function __ProvisionManager_init_unchained() internal onlyInitializing { + _setProvisionTokensRange(type(uint256).min, type(uint256).max); + _setDelegationRatioRange(type(uint32).min, type(uint32).max); + _setVerifierCutRange(type(uint32).min, type(uint32).max); + _setThawingPeriodRange(type(uint64).min, type(uint64).max); } /** - * @notice Verifies and accepts the provision of a service provider in the {Graph Horizon staking - * contract}. + * @notice Verifies and accepts the provision parameters of a service provider in + * the {HorizonStaking} contract. * @dev Checks the pending provision parameters, not the current ones. * * Emits a {ProvisionAccepted} event. @@ -58,76 +128,186 @@ abstract contract ProvisionManager is GraphDirectory, ProvisionManagerV1Storage _graphStaking().acceptProvisionParameters(_serviceProvider); } - // -- Provision Parameters: setters -- + // -- checks -- + + /** + * @notice Checks if the provision tokens of a service provider are within the valid range. + * @param _serviceProvider The address of the service provider. + */ + function _checkProvisionTokens(address _serviceProvider) internal view virtual { + IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); + _checkProvisionTokens(provision); + } + + /** + * @notice Checks if the provision tokens of a service provider are within the valid range. + * @param _provision The provision to check. + */ + function _checkProvisionTokens(IHorizonStaking.Provision memory _provision) internal view virtual { + _checkValueInRange(_provision.tokens, minimumProvisionTokens, maximumProvisionTokens, "tokens"); + } + + /** + * @notice Checks if the delegation ratio of a service provider is within the valid range. + * @param _serviceProvider The address of the service provider. + */ + function _checkProvisionDelegationRatio(address _serviceProvider) internal view virtual { + IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); + _checkProvisionDelegationRatio(provision, _serviceProvider); + } + + /** + * @notice Checks if the delegation ratio of a service provider is within the valid range. + * @param _provision The provision to check. + * @param _serviceProvider The address of the service provider. + */ + function _checkProvisionDelegationRatio( + IHorizonStaking.Provision memory _provision, + address _serviceProvider + ) internal view virtual { + (uint32 delegationRatioMin, uint32 delegationRatioMax) = _getDelegationRatioRange(); + if (delegationRatioMin == type(uint32).min && delegationRatioMax == type(uint32).max) return; + + uint256 delegatedTokens = _graphStaking().getDelegatedTokensAvailable(_serviceProvider, address(this)); + uint256 delegationRatioToCheck = uint32(delegatedTokens / (_provision.tokens - _provision.tokensThawing)); + _checkValueInRange(delegationRatioToCheck, delegationRatioMin, delegationRatioMax, "delegationRatio"); + } + + /** + * @notice Checks if the provision parameters of a service provider are within the valid range. + * @param _serviceProvider The address of the service provider. + * @param _checkPending If true, checks the pending provision parameters. + */ + function _checkProvisionParameters(address _serviceProvider, bool _checkPending) internal view virtual { + IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); + _checkProvisionParameters(provision, _checkPending); + } + + /** + * @notice Checks if the provision parameters of a service provider are within the valid range. + * @param _provision The provision to check. + * @param _checkPending If true, checks the pending provision parameters instead of the current ones. + */ + function _checkProvisionParameters( + IHorizonStaking.Provision memory _provision, + bool _checkPending + ) internal view virtual { + (uint64 thawingPeriodMin, uint64 thawingPeriodMax) = _getThawingPeriodRange(); + if (thawingPeriodMin != type(uint64).min || thawingPeriodMax != type(uint64).max) { + uint64 thawingPeriodToCheck = _checkPending ? _provision.thawingPeriodPending : _provision.thawingPeriod; + _checkValueInRange(thawingPeriodToCheck, thawingPeriodMin, thawingPeriodMax, "thawingPeriod"); + } + + (uint32 verifierCutMin, uint32 verifierCutMax) = _getVerifierCutRange(); + if (verifierCutMin != type(uint32).min || verifierCutMax != type(uint32).max) { + uint32 maxVerifierCutToCheck = _checkPending ? _provision.maxVerifierCutPending : _provision.maxVerifierCut; + _checkValueInRange(maxVerifierCutToCheck, verifierCutMin, verifierCutMax, "maxVerifierCut"); + } + } + + // -- setters -- + + /** + * @notice Sets the range for the provision tokens. + * @param _min The minimum allowed value for the provision tokens. + * @param _max The maximum allowed value for the provision tokens. + */ function _setProvisionTokensRange(uint256 _min, uint256 _max) internal { minimumProvisionTokens = _min; maximumProvisionTokens = _max; + emit ProvisionTokensRangeSet(_min, _max); } + /** + * @notice Sets the range for the delegation ratio. + * @param _min The minimum allowed value for the delegation ratio. + * @param _max The maximum allowed value for the delegation ratio. + */ function _setDelegationRatioRange(uint32 _min, uint32 _max) internal { minimumDelegationRatio = _min; maximumDelegationRatio = _max; + emit DelegationRatioRangeSet(_min, _max); } + /** + * @notice Sets the range for the verifier cut. + * @param _min The minimum allowed value for the max verifier cut. + * @param _max The maximum allowed value for the max verifier cut. + */ function _setVerifierCutRange(uint32 _min, uint32 _max) internal { minimumVerifierCut = _min; maximumVerifierCut = _max; + emit VerifierCutRangeSet(_min, _max); } + /** + * @notice Sets the range for the thawing period. + * @param _min The minimum allowed value for the thawing period. + * @param _max The maximum allowed value for the thawing period. + */ function _setThawingPeriodRange(uint64 _min, uint64 _max) internal { minimumThawingPeriod = _min; maximumThawingPeriod = _max; + emit ThawingPeriodRangeSet(_min, _max); } - function _checkProvisionTokens(address _serviceProvider) internal view virtual { - IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); - _checkValueInRange(provision.tokens, minimumProvisionTokens, maximumProvisionTokens, "tokens"); - } + // -- getters -- - function _checkProvisionDelegationRatio(address _serviceProvider) internal view virtual { - IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); - uint256 delegatedTokens = _graphStaking().getDelegatedTokensAvailable(_serviceProvider, address(this)); - - (uint32 delegationRatioMin, uint32 delegationRatioMax) = _getDelegationRatioRange(); - uint256 delegationRatioToCheck = uint32(delegatedTokens / (provision.tokens - provision.tokensThawing)); - _checkValueInRange(delegationRatioToCheck, delegationRatioMin, delegationRatioMax, "delegationRatio"); - } - - function _checkProvisionParameters(address _serviceProvider, bool _checkPending) internal view virtual { - IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); - - (uint64 thawingPeriodMin, uint64 thawingPeriodMax) = _getThawingPeriodRange(); - uint64 thawingPeriodToCheck = _checkPending ? provision.thawingPeriodPending : provision.thawingPeriod; - _checkValueInRange(thawingPeriodToCheck, thawingPeriodMin, thawingPeriodMax, "thawingPeriod"); - - (uint32 verifierCutMin, uint32 verifierCutMax) = _getVerifierCutRange(); - uint32 maxVerifierCutToCheck = _checkPending ? provision.maxVerifierCutPending : provision.maxVerifierCut; - _checkValueInRange(maxVerifierCutToCheck, verifierCutMin, verifierCutMax, "maxVerifierCut"); - } - - // -- Provision Parameters: getters -- + /** + * @notice Gets the range for the provision tokens. + * @return min The minimum allowed value for the provision tokens. + * @return max The maximum allowed value for the provision tokens. + */ function _getProvisionTokensRange() internal view virtual returns (uint256 min, uint256 max) { return (minimumProvisionTokens, maximumProvisionTokens); } + /** + * @notice Gets the range for the delegation ratio. + * @return min The minimum allowed value for the delegation ratio. + * @return max The maximum allowed value for the delegation ratio. + */ function _getDelegationRatioRange() internal view virtual returns (uint32 min, uint32 max) { return (minimumDelegationRatio, maximumDelegationRatio); } + /** + * @notice Gets the range for the thawing period. + * @return min The minimum allowed value for the thawing period. + * @return max The maximum allowed value for the thawing period. + */ function _getThawingPeriodRange() internal view virtual returns (uint64 min, uint64 max) { return (minimumThawingPeriod, maximumThawingPeriod); } + /** + * @notice Gets the range for the verifier cut. + * @return min The minimum allowed value for the max verifier cut. + * @return max The maximum allowed value for the max verifier cut. + */ function _getVerifierCutRange() internal view virtual returns (uint32 min, uint32 max) { return (minimumVerifierCut, maximumVerifierCut); } + /** + * @notice Gets a provision from the {HorizonStaking} contract. + * @dev Requirements: + * - The provision must exist. + * @param _serviceProvider The address of the service provider. + */ function _getProvision(address _serviceProvider) internal view returns (IHorizonStaking.Provision memory) { IHorizonStaking.Provision memory provision = _graphStaking().getProvision(_serviceProvider, address(this)); - require(provision.createdAt != 0, ProvisionManagerProvisionNotFound(_serviceProvider, address(this))); + require(provision.createdAt != 0, ProvisionManagerProvisionNotFound(_serviceProvider)); return provision; } + /** + * @notice Checks if a value is within a valid range. + * @param _value The value to check. + * @param _min The minimum allowed value. + * @param _max The maximum allowed value. + * @param _revertMessage The revert message to display if the value is out of range. + */ function _checkValueInRange(uint256 _value, uint256 _min, uint256 _max, bytes memory _revertMessage) private pure { require(_value.isInRange(_min, _max), ProvisionManagerInvalidValue(_revertMessage, _value, _min, _max)); } diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index 7f4e507a5..acc24d5a0 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +/** + * @title Storage layout for the {ProvisionManager} helper contract. + */ abstract contract ProvisionManagerV1Storage { /// @notice The minimum amount of tokens required to register a provision in the data service uint256 public minimumProvisionTokens; diff --git a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol index 3cbc93aa0..1f7f0b3d2 100644 --- a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol +++ b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.26; import { LibFixedMath } from "../../libraries/LibFixedMath.sol"; /** - * @title ExponentialRebates contract + * @title ExponentialRebates library * @notice A library to compute query fee rebates using an exponential formula * @dev This is only used for backwards compatibility in HorizonStaking, and should * be removed after the transition period. diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 29dc8e9e1..f39beed4c 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -62,6 +62,7 @@ contract SubgraphService is function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external override initializer { __Ownable_init(msg.sender); + __DataService_init(); __DataServicePausable_init(); __AllocationManager_init("SubgraphService", "1.0"); diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 0e67014dc..5a4a9c58f 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -81,12 +81,12 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca error AllocationManagerAllocationSameSize(address allocationId, uint256 tokens); error AllocationManagerInvalidZeroPOI(); - function __AllocationManager_init(string memory name, string memory version) internal { + function __AllocationManager_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init(name, version); __AllocationManager_init_unchained(name, version); } - function __AllocationManager_init_unchained(string memory name, string memory version) internal {} + function __AllocationManager_init_unchained(string memory name, string memory version) internal onlyInitializing {} function setRewardsDestination(address rewardsDestination) external { _setRewardsDestination(msg.sender, rewardsDestination); diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index 535774c1a..c6ed521b6 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -4,9 +4,10 @@ pragma solidity 0.8.26; import { AttestationManagerV1Storage } from "./AttestationManagerStorage.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { Attestation } from "../libraries/Attestation.sol"; -abstract contract AttestationManager is AttestationManagerV1Storage { +abstract contract AttestationManager is Initializable, AttestationManagerV1Storage { bytes32 private constant RECEIPT_TYPE_HASH = keccak256("Receipt(bytes32 requestCID,bytes32 responseCID,bytes32 subgraphDeploymentID)"); @@ -16,11 +17,11 @@ abstract contract AttestationManager is AttestationManagerV1Storage { bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); bytes32 private constant DOMAIN_SALT = 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; - function __AttestationManager_init() internal { + function __AttestationManager_init() internal onlyInitializing { __AttestationManager_init_unchained(); } - function __AttestationManager_init_unchained() internal { + function __AttestationManager_init_unchained() internal onlyInitializing { _domainSeparator = keccak256( abi.encode( DOMAIN_TYPE_HASH, From 641842e8adb1b08f3cf0321b09aa9975ed141e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 30 May 2024 17:16:24 -0300 Subject: [PATCH 091/277] docs: add natspec to payments protocol contracts and libraries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/IGraphPayments.sol | 46 ++- .../interfaces/IPaymentsCollector.sol | 38 +++ .../contracts/interfaces/IPaymentsEscrow.sol | 273 ++++++++++++++++-- .../contracts/interfaces/ITAPCollector.sol | 54 +++- .../contracts/libraries/Denominations.sol | 8 +- .../contracts/libraries/LinkedList.sol | 57 ++++ .../horizon/contracts/libraries/PPMMath.sol | 40 ++- .../horizon/contracts/libraries/UintRange.sol | 14 +- .../contracts/payments/GraphPayments.sol | 22 +- .../contracts/payments/PaymentsEscrow.sol | 146 ++++++---- .../payments/collectors/TAPCollector.sol | 41 ++- 11 files changed, 619 insertions(+), 120 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index c3889222f..86054ad7d 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -1,16 +1,35 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +/** + * @title Interface for the {GraphPayments} contract + * @notice This contract is part of the Graph Horizon payments protocol. It's designed + * to pull funds (GRT) from the {PaymentsEscrow} and distribute them according to a + * set of pre established rules. + */ interface IGraphPayments { - // Payment types + /** + * @notice Types of payments that are supported by the payments protocol + * @dev + */ enum PaymentTypes { QueryFee, IndexingFee, IndexingRewards } - event GraphPaymentsCollected( - address indexed sender, + /** + * @notice Emitted when a payment is collected + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param dataService The address of the data service + * @param tokensReceiver Amount of tokens for the receiver + * @param tokensDelegationPool Amount of tokens for delegators + * @param tokensDataService Amount of tokens for the data service + * @param tokensProtocol Amount of tokens charged as protocol tax + */ + event PaymentCollected( + address indexed payer, address indexed receiver, address indexed dataService, uint256 tokensReceiver, @@ -18,13 +37,28 @@ interface IGraphPayments { uint256 tokensDataService, uint256 tokensProtocol ); - // -- Errors -- - error GraphPaymentsInsufficientTokens(uint256 available, uint256 required); + /** + * @notice Emitted when there are insufficient tokens to pay the required amount + * @param tokens The amount of tokens available + * @param minTokens The amount of tokens being collected + */ + error GraphPaymentsInsufficientTokens(uint256 tokens, uint256 minTokens); + /** + * @notice Initialize the contract + */ function initialize() external; - // collect funds from a sender, pay cuts and forward the rest to the receiver + /** + * @notice Collects funds from a payer. + * It will pay cuts to all relevant parties and forward the rest to the receiver. + * @param paymentType The type of payment as defined in {IGraphPayments} + * @param receiver The address of the receiver + * @param tokens The amount of tokens being collected + * @param dataService The address of the data service + * @param tokensDataService The amount of tokens that should be sent to the data service + */ function collect( PaymentTypes paymentType, address receiver, diff --git a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol index f076ef3e0..176f6284b 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol @@ -4,6 +4,44 @@ pragma solidity 0.8.26; import { IGraphPayments } from "./IGraphPayments.sol"; +/** + * @title Interface for a payments collector contract as defined by Graph Horizon payments protocol + * @notice Contracts implementing this interface can be used with the payments protocol. First, a payer must + * approve the collector to collect payments on their behalf. Only then can payment collection be initiated + * using the collector contract. + * + * @dev It's important to note that it's the collector contract's responsibility to validate the payment + * request is legitimate. + */ interface IPaymentsCollector { + /** + * @notice Emitted when a payment is collected + * @param paymentType The payment type collected as defined by {IGraphPayments} + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param tokensReceiver The amount of tokens received by the receiver + * @param dataService The address of the data service + * @param tokensDataService The amount of tokens received by the data service + */ + event PaymentCollected( + IGraphPayments.PaymentTypes indexed paymentType, + address indexed payer, + address receiver, + uint256 tokensReceiver, + address indexed dataService, + uint256 tokensDataService + ); + + /** + * @notice Initiate a payment collection through the payments protocol + * @dev This function should require the caller to present some form of evidence of the payer's debt to + * the receiver. The collector should validate this evidence and, if valid, collect the payment. + * + * Emits a {PaymentCollected} event + * + * @param paymentType The payment type to collect, as defined by {IGraphPayments} + * @param data Additional data required for the payment collection. Will vary depending on the collector + * implementation. + */ function collect(IGraphPayments.PaymentTypes paymentType, bytes memory data) external returns (uint256); } diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 7b39d77df..6d9396d00 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -3,28 +3,90 @@ pragma solidity 0.8.26; import { IGraphPayments } from "./IGraphPayments.sol"; +/** + * @title Interface for the {PaymentsEscrow} contract + * @notice This contract is part of the Graph Horizon payments protocol. It holds the funds (GRT) + * for payments made through the payments protocol for services provided + * via a Graph Horizon data service. + * + * Payers deposit funds on the escrow, signalling their ability to pay for a service, and only + * being able to retrieve them after a thawing period. Receivers collect funds from the escrow, + * provided the payer has authorized them. The payer authorization is delegated to a payment + * collector contract which implements the {IPaymentsCollector} interface. + */ interface IPaymentsEscrow { + /// @notice Escrow account for a payer-receiver pair struct EscrowAccount { - uint256 balance; // Total escrow balance for a sender-receiver pair - uint256 tokensThawing; // Amount of escrow currently being thawed - uint256 thawEndTimestamp; // Timestamp at which thawing period ends (zero if not thawing) + // Total token balance for the payer-receiver pair + uint256 balance; + // Amount of tokens currently being thawed + uint256 tokensThawing; + // Timestamp at which thawing period ends (zero if not thawing) + uint256 thawEndTimestamp; } - // Collector + /// @notice Details for a payer-collector pair + /// @dev Collectors can be removed only after a thawing period struct Collector { + // Whether the collector is authorized to collect funds bool authorized; + // Amount of tokens the collector is allowed to collect uint256 allowance; + // Timestamp at which the collector thawing period ends (zero if not thawing) uint256 thawEndTimestamp; } - // -- Events -- + /** + * @notice Emitted when a payer authorizes a collector to collect funds + * @param payer The address of the payer + * @param collector The address of the collector + */ + event AuthorizedCollector(address indexed payer, address indexed collector); + + /** + * @notice Emitted when a payer thaws a collector + * @param payer The address of the payer + * @param collector The address of the collector + */ + event ThawCollector(address indexed payer, address indexed collector); + + /** + * @notice Emitted when a payer cancels the thawing of a collector + * @param payer The address of the payer + * @param collector The address of the collector + */ + event CancelThawCollector(address indexed payer, address indexed collector); - event AuthorizedCollector(address indexed payer, address indexed dataService); - event ThawCollector(address indexed payer, address indexed dataService); - event CancelThawCollector(address indexed payer, address indexed dataService); - event RevokeCollector(address indexed payer, address indexed dataService); + /** + * @notice Emitted when a payer revokes a collector authorization. + * @param payer The address of the payer + * @param collector The address of the collector + */ + event RevokeCollector(address indexed payer, address indexed collector); + + /** + * @notice Emitted when a payer deposits funds into the escrow for a payer-receiver pair + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param tokens The amount of tokens deposited + */ event Deposit(address indexed payer, address indexed receiver, uint256 tokens); + + /** + * @notice Emitted when a payer cancels an escrow thawing + * @param payer The address of the payer + * @param receiver The address of the receiver + */ event CancelThaw(address indexed payer, address indexed receiver); + + /** + * @notice Emitted when a payer thaws funds from the escrow for a payer-receiver pair + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param tokens The amount of tokens thawed + * @param totalTokensThawing The total amount of tokens being thawed + * @param thawEndTimestamp The timestamp at which the thawing period ends + */ event Thaw( address indexed payer, address indexed receiver, @@ -32,43 +94,206 @@ interface IPaymentsEscrow { uint256 totalTokensThawing, uint256 thawEndTimestamp ); + + /** + * @notice Emitted when a payer withdraws funds from the escrow for a payer-receiver pair + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param tokens The amount of tokens withdrawn + */ event Withdraw(address indexed payer, address indexed receiver, uint256 tokens); + + /** + * @notice Emitted when a collector collects funds from the escrow for a payer-receiver pair + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param tokens The amount of tokens collected + */ event EscrowCollected(address indexed payer, address indexed receiver, uint256 tokens); // -- Errors -- - error PaymentsEscrowInsufficientTokensThawing(); - error PaymentsEscrowInsufficientBalance(uint256 available, uint256 required); + /** + * @notice Thrown when the available balance is insufficient to perform an operation + * @param balance The current balance + * @param minBalance The minimum required balance + */ + error PaymentsEscrowInsufficientBalance(uint256 balance, uint256 minBalance); + + /** + * @notice Thrown when a thawing is expected to be in progress but it is not + */ error PaymentsEscrowNotThawing(); + + /** + * @notice Thrown when a thawing is still in progress + * @param currentTimestamp The current timestamp + * @param thawEndTimestamp The timestamp at which the thawing period ends + */ error PaymentsEscrowStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); + + /** + * @notice Thrown when setting the thawing period to a value greater than the maximum + * @param thawingPeriod The thawing period + * @param maxThawingPeriod The maximum thawing period + */ error PaymentsEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); - error PaymentsEscrowCollectorNotAuthorized(address sender, address dataService); - error PaymentsEscrowInsufficientAllowance(uint256 current, uint256 required); - error PaymentsEscrowInconsistentAllowance(uint256 current, uint256 required); + + /** + * @notice Thrown when a collector is not authorized to collect funds + * @param payer The address of the payer + * @param collector The amount of tokens the collector is allowed to collect + */ + error PaymentsEscrowCollectorNotAuthorized(address payer, address collector); + + /** + * @notice Thrown when a collector has insufficient allowance to collect funds + * @param allowance The current allowance + * @param minAllowance The minimum required allowance + */ + error PaymentsEscrowInsufficientAllowance(uint256 allowance, uint256 minAllowance); + + /** + * @notice Thrown when attempting to decrease a collector's allowance + * @param current The current allowance + * @param target The target allowance + */ + error PaymentsEscrowInconsistentAllowance(uint256 current, uint256 target); + + /** + * @notice Thrown when the contract balance is not consistent with the collection amount + * @param balanceBefore The balance before the collection + * @param balanceAfter The balance after the collection + * @param tokens The amount of tokens collected + */ error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); - function approveCollector(address dataService, uint256 thawingPeriod) external; - function thawCollector(address dataService) external; - function cancelThawCollector(address dataService) external; - function revokeCollector(address dataService) external; - // Deposit funds into the escrow for a receiver + /** + * @notice Authorize a collector to collect funds from the payer's escrow + * @dev This function can only be used to increase the allowance of a collector. + * To reduce it the authorization must be revoked and a new one must be created. + * + * Requirements: + * - `allowance` must be greater than the current allowance + * + * Emits an {AuthorizedCollector} event + * + * @param collector The address of the collector + * @param allowance The amount of tokens the collector is allowed to collect + */ + function approveCollector(address collector, uint256 allowance) external; + + /** + * @notice Thaw a collector's collector authorization + * @dev The thawing period is defined by the `REVOKE_COLLECTOR_THAWING_PERIOD` constant + * + * Emits a {ThawCollector} event + * + * @param collector The address of the collector + */ + function thawCollector(address collector) external; + + /** + * @notice Cancel a collector's authorization thawing + * @dev Requirements: + * - `collector` must be thawing + * + * Emits a {CancelThawCollector} event + * + * @param collector The address of the collector + */ + function cancelThawCollector(address collector) external; + + /** + * @notice Revoke a collector's authorization. + * Removes the collector from the list of authorized collectors. + * @dev Requirements: + * - `collector` must have thawed + * + * Emits a {RevokeCollector} event + * + * @param collector The address of the collector + */ + function revokeCollector(address collector) external; + + /** + * @notice Deposits funds into the escrow for a payer-receiver pair, where + * the payer is the transaction caller. + * @dev Emits a {Deposit} event + * @param receiver The address of the receiver + * @param tokens The amount of tokens to deposit + */ function deposit(address receiver, uint256 tokens) external; - // Requests to thaw a specific amount of escrow from a receiver's escrow account + /** + * @notice Deposits funds into the escrow for a payer-receiver pair, where + * the payer can be specified. + * @dev Emits a {Deposit} event + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param tokens The amount of tokens to deposit + */ + function depositTo(address payer, address receiver, uint256 tokens) external; + + /** + * @notice Thaw a specific amount of escrow from a payer-receiver's escrow account. + * The payer is the transaction caller. + * If `tokens` is zero and funds were already thawing it will cancel the thawing. + * Note that repeated calls to this function will overwrite the previous thawing amount + * and reset the thawing period. + * @dev Requirements: + * - `tokens` must be less than or equal to the available balance + * + * Emits a {Thaw} event. If `tokens` is zero it will emit a {CancelThaw} event. + * + * @param receiver The address of the receiver + * @param tokens The amount of tokens to thaw + */ function thaw(address receiver, uint256 tokens) external; - // Withdraws all thawed escrow from a receiver's escrow account + /** + * @notice Withdraws all thawed escrow from a payer-receiver's escrow account. + * The payer is the transaction caller. + * Note that the withdrawn funds might be less than the thawed amount if there were + * payment collections in the meantime. + * @dev Requirements: + * - Funds must be thawed + * + * Emits a {Withdraw} event + * + * @param receiver The address of the receiver + */ function withdraw(address receiver) external; - // Collect from escrow for a receiver using sender's deposit + /** + * @notice Collects funds from the payer-receiver's escrow and sends them to {GraphPayments} for + * distribution using the Graph Horizon Payments protocol. + * The function will revert if there are not enough funds in the escrow. + * @dev Requirements: + * - `collector` needs to be authorized by the payer and have enough allowance + * + * Emits an {EscrowCollected} event + * + * @param paymentType The type of payment being collected as defined in the {IGraphPayments} interface + * @param payer The address of the payer + * @param receiver The address of the receiver + * @param tokens The amount of tokens to collect + * @param collector The address of the collector + * @param tokensDataService The amount of tokens that {GraphPayments} should send to the data service + */ function collect( IGraphPayments.PaymentTypes paymentType, address payer, address receiver, uint256 tokens, - address dataService, + address collector, uint256 tokensDataService ) external; - function getBalance(address sender, address receiver) external view returns (uint256); + /** + * @notice Get the balance of a payer-receiver pair + * @param payer The address of the payer + * @param receiver The address of the receiver + */ + function getBalance(address payer, address receiver) external view returns (uint256); } diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 46209bb2d..2e5a47c05 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -4,29 +4,63 @@ pragma solidity 0.8.26; import { IGraphPayments } from "./IGraphPayments.sol"; import { IPaymentsCollector } from "./IPaymentsCollector.sol"; +/** + * @title Interface for the {TAPCollector} contract + * @dev Implements the {IPaymentCollector} interface as defined by the Graph + * Horizon payments protocol. + * @notice Implements a payments collector contract that can be used to collect + * payments using a TAP RAV (Receipt Aggregate Voucher). + */ interface ITAPCollector is IPaymentsCollector { + /// @notice The Receipt Aggregate Voucher (RAV) struct struct ReceiptAggregateVoucher { + // The address of the data service the RAV was issued to address dataService; + // The address of the service provider the RAV was issued to address serviceProvider; + // The RAV timestamp, indicating the latest TAP Receipt in the RAV uint64 timestampNs; + // Total amount owed to the service provider since the beginning of the + // payer-service provider relationship, including all debt that is already paid for. uint128 valueAggregate; + // Arbitrary metadata to extend functionality if a data service requires it bytes metadata; } + /// @notice A struct representing a signed RAV struct SignedRAV { + // The RAV ReceiptAggregateVoucher rav; - bytes signature; // 65 bytes: r (32 Bytes) || s (32 Bytes) || v (1 Byte) + // Signature - 65 bytes: r (32 Bytes) || s (32 Bytes) || v (1 Byte) + bytes signature; } - event TAPCollectorCollected( - IGraphPayments.PaymentTypes indexed paymentType, - address indexed payer, - address receiver, - uint256 tokensReceiver, - address indexed dataService, - uint256 tokensDataService - ); - + /** + * Trown when the caller is not the data service the RAV was issued to + * @param caller The address of the caller + * @param dataService The address of the data service + */ error TAPCollectorCallerNotDataService(address caller, address dataService); + + /** + * @notice Thrown when the tokens collected are inconsistent with the collection history + * Each RAV should have a value greater than the previous one + * @param tokens The amount of tokens in the RAV + * @param tokensCollected The amount of tokens already collected + */ error TAPCollectorInconsistentRAVTokens(uint256 tokens, uint256 tokensCollected); + + /** + * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). + * @param signedRAV The SignedRAV containing the RAV and its signature. + * @return The address of the signer. + */ + function recoverRAVSigner(SignedRAV calldata signedRAV) external view returns (address); + + /** + * @dev Computes the hash of a ReceiptAggregateVoucher (RAV). + * @param rav The RAV for which to compute the hash. + * @return The hash of the RAV. + */ + function encodeRAV(ReceiptAggregateVoucher calldata rav) external view returns (bytes32); } diff --git a/packages/horizon/contracts/libraries/Denominations.sol b/packages/horizon/contracts/libraries/Denominations.sol index 5652f50a0..ae3adab94 100644 --- a/packages/horizon/contracts/libraries/Denominations.sol +++ b/packages/horizon/contracts/libraries/Denominations.sol @@ -2,13 +2,19 @@ pragma solidity 0.8.26; /** - * @title Denominations + * @title Denominations library * @dev Provides a list of ground denominations for those tokens that cannot be represented by an ERC20. * For now, the only needed is the native token that could be ETH, MATIC, or other depending on the layer being operated. */ library Denominations { + /// @notice The address of the native token, i.e ETH address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + /** + * @notice Checks if a token is the native token + * @param token The token address to check + * @return True if the token is the native token, false otherwise + */ function isNativeToken(address token) internal pure returns (bool) { return token == NATIVE_TOKEN; } diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index d58d3f5cd..99bf682ea 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -2,19 +2,51 @@ pragma solidity 0.8.26; +/** + * @title LinkedList library + * @notice A library to manage singly linked lists. + * + * The library makes no assumptions about the contents of the items, the only + * requirements on the items are: + * - they must be represented by a unique bytes32 id + * - the id of the item must not be bytes32(0) + * - each item must have a reference to the next item in the list + * + * A contract using this library must store: + * - a LinkedList.List to keep track of the list metadata + * - a mapping from bytes32 to the item data + */ library LinkedList { using LinkedList for List; + /// @notice Represents a linked list struct List { + // The head of the list bytes32 head; + // The tail of the list bytes32 tail; + // A nonce, which can optionally be used to generate unique ids uint256 nonce; + // The number of items in the list uint256 count; } + + /// @notice Empty bytes constant bytes internal constant NULL_BYTES = bytes(""); + /** + * @notice Thrown when trying to remove an item from an empty list + */ error LinkedListEmptyList(); + /** + * @notice Adds an item to the list. + * The item is added to the end of the list. + * @dev Note that this function will not take care of linking the + * old tail to the new item. The caller should take care of this. + * @param self The list metadata + * @param id The id of the item to add + */ function add(List storage self, bytes32 id) internal { self.tail = id; self.nonce += 1; @@ -22,6 +54,15 @@ library LinkedList { self.count += 1; } + /** + * @notice Removes an item from the list. + * The item is removed from the beginning of the list. + * @param self The list metadata + * @param getNextItem A function to get the next item in the list. It should take + * the id of the current item and return the id of the next item. + * @param deleteItem A function to delete an item. This should delete the item from + * the contract storage. It takes the id of the item to delete. + */ function remove( List storage self, function(bytes32) view returns (bytes32) getNextItem, @@ -36,6 +77,22 @@ library LinkedList { return self.head; } + /** + * @notice Traverses the list and processes each item. + * @param self The list metadata + * @param getNextItem A function to get the next item in the list. It should take + * the id of the current item and return the id of the next item. + * @param processItem A function to process an item. The function should take the id of the item + * and an accumulator, and return: + * - a boolean indicating whether the traversal should stop + * - a boolean indicating whether the item should be deleted + * - an accumulator to pass data between iterations + * @param deleteItem A function to delete an item. This should delete the item from + * the contract storage. It takes the id of the item to delete. + * @param processInitAcc The initial accumulator data + * @param iterations The maximum number of iterations to perform. If 0, the traversal will continue + * until the end of the list. + */ function traverse( List storage self, function(bytes32) view returns (bytes32) getNextItem, diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index f18e089ab..1496be4d8 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -1,28 +1,54 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +/** + * @title PPMMath library + * @notice A library for handling calculations with parts per million (PPM) amounts. + */ library PPMMath { /// @notice Maximum value (100%) in parts per million (PPM). uint256 internal constant MAX_PPM = 1_000_000; - error PPMMathInvalidPPM(uint256 ppm); + /** + * @notice Thrown when a value is expected to be in PPM but is not. + * @param value The value that is not in PPM. + */ + error PPMMathInvalidPPM(uint256 value); + + /** + * @notice Thrown when no value in a multiplication is in PPM. + * @param a The first value in the multiplication. + * @param b The second value in the multiplication. + */ error PPMMathInvalidMulPPM(uint256 a, uint256 b); - // one of a or b must be in PPM + /** + * @notice Multiplies two values, one of which must be in PPM. + * @param a The first value. + * @param b The second value. + * @return The result of the multiplication. + */ function mulPPM(uint256 a, uint256 b) internal pure returns (uint256) { require(isValidPPM(a) || isValidPPM(b), PPMMathInvalidMulPPM(a, b)); return (a * b) / MAX_PPM; } - // Calculate the tokens after curation fees first, and subtact that, - // to prevent curation fees from rounding down to zero - // a must be in ppm + /** + * @notice Multiplies two values, one of which must be in PPM, and rounds up the result. + * @param a The first value. + * @param b The second value. + */ function mulPPMRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { require(isValidPPM(b), PPMMathInvalidPPM(b)); return a - mulPPM(MAX_PPM - b, a); } - function isValidPPM(uint256 ppm) internal pure returns (bool) { - return ppm >= 0 && ppm <= MAX_PPM; + /** + * @notice Checks if a value is in PPM. + * @dev A valid PPM value is between 0 and MAX_PPM. + * @param value The value to check. + */ + function isValidPPM(uint256 value) internal pure returns (bool) { + return value >= 0 && value <= MAX_PPM; } } diff --git a/packages/horizon/contracts/libraries/UintRange.sol b/packages/horizon/contracts/libraries/UintRange.sol index 2e722e057..12fe10176 100644 --- a/packages/horizon/contracts/libraries/UintRange.sol +++ b/packages/horizon/contracts/libraries/UintRange.sol @@ -1,10 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +/** + * @title UintRange library + * @notice A library for handling range checks on uint256 values. + */ library UintRange { using UintRange for uint256; - function isInRange(uint256 self, uint256 min, uint256 max) internal pure returns (bool) { - return self >= min && self <= max; + /** + * @notice Checks if a value is in the range [`min`, `max`]. + * @param value The value to check. + * @param min The minimum value of the range. + * @param max The maximum value of the range. + */ + function isInRange(uint256 value, uint256 min, uint256 max) internal pure returns (bool) { + return value >= min && value <= max; } } diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 274337af0..a3e1b2dd7 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -11,21 +11,39 @@ import { PPMMath } from "../libraries/PPMMath.sol"; import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +/** + * @title GraphPayments contract + * @notice This contract is part of the Graph Horizon payments protocol. It's designed + * to pull funds (GRT) from the {PaymentsEscrow} and distribute them according to a + * set of pre established rules. + */ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, IGraphPayments { using TokenUtils for IGraphToken; using PPMMath for uint256; uint256 public immutable PROTOCOL_PAYMENT_CUT; + /** + * @notice Constructor for the {GraphPayments} contract + * @dev This contract is upgradeable however we stil use the constructor to set + * a few immutable variables. + * @param controller The address of the Graph controller + * @param protocolPaymentCut The protocol tax in PPM + */ constructor(address controller, uint256 protocolPaymentCut) GraphDirectory(controller) { PROTOCOL_PAYMENT_CUT = protocolPaymentCut; _disableInitializers(); } + /** + * @notice See {IGraphPayments-initialize} + */ function initialize() external initializer { __Multicall_init(); } - // collect funds from a sender, pay cuts and forward the rest to the receiver + /** + * @notice See {IGraphPayments-collect} + */ function collect( IGraphPayments.PaymentTypes paymentType, address receiver, @@ -57,7 +75,7 @@ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, I uint256 tokensReceiverRemaining = tokens - totalCut; _graphToken().pushTokens(receiver, tokensReceiverRemaining); - emit GraphPaymentsCollected( + emit PaymentCollected( msg.sender, receiver, dataService, diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 5b62863ec..a03ac7409 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -10,29 +10,40 @@ import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils. import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +/** + * @title PaymentsEscrow contract + * @dev Implements the {IPaymentsEscrow} interface + * @notice This contract is part of the Graph Horizon payments protocol. It holds the funds (GRT) + * for payments made through the payments protocol for services provided + * via a Graph Horizon data service. + */ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { using TokenUtils for IGraphToken; - // Authorized collectors - mapping(address sender => mapping(address dataService => IPaymentsEscrow.Collector collector)) + /// @notice Authorization details for payer-collector pairs + mapping(address payer => mapping(address collector => IPaymentsEscrow.Collector collectorDetails)) public authorizedCollectors; - // Stores how much escrow each sender has deposited for each receiver, as well as thawing information - mapping(address sender => mapping(address receiver => IPaymentsEscrow.EscrowAccount escrowAccount)) + /// @notice Escrow account details for payer-receiver pairs + mapping(address payer => mapping(address receiver => IPaymentsEscrow.EscrowAccount escrowAccount)) public escrowAccounts; - // The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation - // This is a precautionary measure to avoid inadvertedly locking funds for too long + /// @notice The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation + /// @dev This is a precautionary measure to avoid inadvertedly locking funds for too long uint256 public constant MAX_THAWING_PERIOD = 90 days; - // Thawing period for authorized collectors + /// @notice Thawing period in seconds for authorized collectors uint256 public immutable REVOKE_COLLECTOR_THAWING_PERIOD; - // The duration (in seconds) in which escrow funds are thawing before they can be withdrawn + /// @notice Thawing period in seconds for escrow funds withdrawal uint256 public immutable WITHDRAW_ESCROW_THAWING_PERIOD; - // -- Constructor -- - + /** + * @notice Construct the PaymentsEscrow contract + * @param controller The address of the controller + * @param revokeCollectorThawingPeriod Thawing period in seconds for authorized collectors + * @param withdrawEscrowThawingPeriod Thawing period in seconds for escrow funds withdrawal + */ constructor( address controller, uint256 revokeCollectorThawingPeriod, @@ -51,35 +62,43 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { WITHDRAW_ESCROW_THAWING_PERIOD = withdrawEscrowThawingPeriod; } - // approve a data service to collect funds - function approveCollector(address dataService, uint256 tokens) external override { - Collector storage collector = authorizedCollectors[msg.sender][dataService]; - require(tokens > collector.allowance, PaymentsEscrowInconsistentAllowance(collector.allowance, tokens)); + /** + * @notice See {IPaymentsEscrow-approveCollector} + */ + function approveCollector(address collector_, uint256 allowance) external override { + Collector storage collector = authorizedCollectors[msg.sender][collector_]; + require(allowance > collector.allowance, PaymentsEscrowInconsistentAllowance(collector.allowance, allowance)); collector.authorized = true; - collector.allowance = tokens; - emit AuthorizedCollector(msg.sender, dataService); + collector.allowance = allowance; + emit AuthorizedCollector(msg.sender, collector_); } - // thaw a data service's collector authorization - function thawCollector(address dataService) external override { - authorizedCollectors[msg.sender][dataService].thawEndTimestamp = + /** + * @notice See {IPaymentsEscrow-thawCollector} + */ + function thawCollector(address collector) external override { + authorizedCollectors[msg.sender][collector].thawEndTimestamp = block.timestamp + REVOKE_COLLECTOR_THAWING_PERIOD; - emit ThawCollector(msg.sender, dataService); + emit ThawCollector(msg.sender, collector); } - // cancel thawing a data service's collector authorization - function cancelThawCollector(address dataService) external override { - require(authorizedCollectors[msg.sender][dataService].thawEndTimestamp != 0, PaymentsEscrowNotThawing()); + /** + * @notice See {IPaymentsEscrow-cancelThawCollector} + */ + function cancelThawCollector(address collector) external override { + require(authorizedCollectors[msg.sender][collector].thawEndTimestamp != 0, PaymentsEscrowNotThawing()); - authorizedCollectors[msg.sender][dataService].thawEndTimestamp = 0; - emit CancelThawCollector(msg.sender, dataService); + authorizedCollectors[msg.sender][collector].thawEndTimestamp = 0; + emit CancelThawCollector(msg.sender, collector); } - // revoke authorized collector - function revokeCollector(address dataService) external override { - Collector storage collector = authorizedCollectors[msg.sender][dataService]; + /** + * @notice See {IPaymentsEscrow-revokeCollector} + */ + function revokeCollector(address collector_) external override { + Collector storage collector = authorizedCollectors[msg.sender][collector_]; require(collector.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); require( @@ -87,43 +106,52 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { PaymentsEscrowStillThawing(block.timestamp, collector.thawEndTimestamp) ); - delete authorizedCollectors[msg.sender][dataService]; - emit RevokeCollector(msg.sender, dataService); + delete authorizedCollectors[msg.sender][collector_]; + emit RevokeCollector(msg.sender, collector_); } - // Deposit funds into the escrow for a receiver + /** + * @notice See {IPaymentsEscrow-deposit} + */ function deposit(address receiver, uint256 tokens) external override { - escrowAccounts[msg.sender][receiver].balance += tokens; - _graphToken().pullTokens(msg.sender, tokens); - emit Deposit(msg.sender, receiver, tokens); + _deposit(msg.sender, receiver, tokens); + } + + /** + * @notice See {IPaymentsEscrow-depositTo} + */ + function depositTo(address payer, address receiver, uint256 tokens) external override { + _deposit(payer, receiver, tokens); } - // Requests to thaw a specific amount of escrow from a receiver's escrow account + /** + * @notice See {IPaymentsEscrow-thaw} + */ function thaw(address receiver, uint256 tokens) external override { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; + + // if amount thawing is zero and requested amount is zero this is an invalid request. + // otherwise if amount thawing is greater than zero and requested amount is zero this + // is a cancel thaw request. if (tokens == 0) { - // if amount thawing is zero and requested amount is zero this is an invalid request. - // otherwise if amount thawing is greater than zero and requested amount is zero this - // is a cancel thaw request. - require(account.tokensThawing != 0, PaymentsEscrowInsufficientTokensThawing()); + require(account.tokensThawing != 0, PaymentsEscrowNotThawing()); account.tokensThawing = 0; account.thawEndTimestamp = 0; emit CancelThaw(msg.sender, receiver); return; } - // Check if the escrow balance is sufficient require(account.balance >= tokens, PaymentsEscrowInsufficientBalance(account.balance, tokens)); - // Set amount to thaw account.tokensThawing = tokens; - // Set when the thaw is complete (thawing period number of seconds after current timestamp) account.thawEndTimestamp = block.timestamp + WITHDRAW_ESCROW_THAWING_PERIOD; emit Thaw(msg.sender, receiver, tokens, account.tokensThawing, account.thawEndTimestamp); } - // Withdraws all thawed escrow from a receiver's escrow account + /** + * @notice See {IPaymentsEscrow-withdraw} + */ function withdraw(address receiver) external override { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; require(account.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); @@ -135,14 +163,16 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { // Amount is the minimum between the amount being thawed and the actual balance uint256 tokens = account.tokensThawing > account.balance ? account.balance : account.tokensThawing; - account.balance -= tokens; // Reduce the balance by the withdrawn amount (no underflow risk) + account.balance -= tokens; account.tokensThawing = 0; account.thawEndTimestamp = 0; _graphToken().pushTokens(msg.sender, tokens); emit Withdraw(msg.sender, receiver, tokens); } - // Collect from escrow for a receiver using sender's deposit + /** + * @notice See {IPaymentsEscrow-collect} + */ function collect( IGraphPayments.PaymentTypes paymentType, address payer, @@ -156,17 +186,14 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { require(collector.authorized, PaymentsEscrowCollectorNotAuthorized(payer, msg.sender)); require(collector.allowance >= tokens, PaymentsEscrowInsufficientAllowance(collector.allowance, tokens)); - // Reduce amount from approved collector - collector.allowance -= tokens; - - // Collect tokens from PaymentsEscrow up to amount available + // Check if there are enough funds in the escrow account EscrowAccount storage account = escrowAccounts[payer][receiver]; - uint256 availableTokens = account.balance - account.tokensThawing; - require(availableTokens >= tokens, PaymentsEscrowInsufficientBalance(availableTokens, tokens)); + require(account.balance >= tokens, PaymentsEscrowInsufficientBalance(account.balance, tokens)); + // Reduce amount from approved collector and account balance + collector.allowance -= tokens; account.balance -= tokens; - // Approve tokens so GraphPayments can pull them uint256 balanceBefore = _graphToken().balanceOf(address(this)); _graphToken().approve(address(_graphPayments()), tokens); @@ -181,9 +208,22 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { emit EscrowCollected(payer, receiver, tokens); } - // Get the balance of a sender-receiver pair + /** + * @notice See {IPaymentsEscrow-getBalance} + */ function getBalance(address payer, address receiver) external view override returns (uint256) { EscrowAccount storage account = escrowAccounts[payer][receiver]; return account.balance - account.tokensThawing; } + + /** + * @notice See {IPaymentsEscrow-deposit} + * @param receiver The address of the receiver + * @param tokens The amount of tokens to deposit + */ + function _deposit(address payer, address receiver, uint256 tokens) internal { + escrowAccounts[payer][receiver].balance += tokens; + _graphToken().pullTokens(msg.sender, tokens); + emit Deposit(payer, receiver, tokens); + } } diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index b535a72de..a80e08cdf 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -11,22 +11,31 @@ import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** - * @title TAPVerifier - * @dev A contract for verifying receipt aggregation vouchers. + * @title TAPCollector contract + * @dev Implements the {ITAPCollector} and {IPaymentCollector} interfaces. + * @notice A payments collector contract that can be used to collect payments using a TAP RAV (Receipt Aggregate Voucher). + * @dev Note that the contract expects the RAV aggregate value to be monotonically increasing, each successive RAV for the same + * (data service-payer-receiver) tuple should have a value greater than the previous one. The contract will keep track of the tokens + * already collected and calculate the difference to collect. */ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { using PPMMath for uint256; + /// @notice The EIP712 typehash for the ReceiptAggregateVoucher struct bytes32 private constant EIP712_RAV_TYPEHASH = keccak256( "ReceiptAggregateVoucher(address dataService, address serviceProvider,uint64 timestampNs,uint128 valueAggregate,bytes metadata)" ); + /// @notice Tracks the amount of tokens already collected by a data service from a payer to a receiver mapping(address dataService => mapping(address receiver => mapping(address payer => uint256 tokens))) public tokensCollected; /** - * @dev Constructs a new instance of the TAPVerifier contract. + * @notice Constructs a new instance of the TAPVerifier contract. + * @param eip712Name The name of the EIP712 domain. + * @param eip712Version The version of the EIP712 domain. + * @param controller The address of the Graph controller. */ constructor( string memory eip712Name, @@ -35,11 +44,12 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { ) EIP712(eip712Name, eip712Version) GraphDirectory(controller) {} /** - * @notice Verify validity of a SignedRAV + * @notice Initiate a payment collection through the payments protocol + * See {IGraphPayments.collect}. * @dev Caller must be the data service the RAV was issued to. * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. */ - function collect(IGraphPayments.PaymentTypes paymentType, bytes memory data) external returns (uint256) { + function collect(IGraphPayments.PaymentTypes paymentType, bytes memory data) external override returns (uint256) { (SignedRAV memory signedRAV, uint256 dataServiceCut) = abi.decode(data, (SignedRAV, uint256)); require( signedRAV.rav.dataService == msg.sender, @@ -72,34 +82,35 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { tokensCollected[dataService][receiver][payer] = tokensRAV; } - emit TAPCollectorCollected(paymentType, payer, receiver, tokensToCollect, dataService, tokensDataService); + emit PaymentCollected(paymentType, payer, receiver, tokensToCollect, dataService, tokensDataService); return tokensToCollect; } /** - * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). - * @param signedRAV The SignedRAV containing the RAV and its signature. - * @return The address of the signer. - * @notice REVERT: This function may revert if ECDSA.recover fails, check ECDSA library for details. + * @notice See {ITAPCollector.recoverRAVSigner} */ - function recoverRAVSigner(SignedRAV calldata signedRAV) public view returns (address) { + function recoverRAVSigner(SignedRAV calldata signedRAV) external view override returns (address) { return _recoverRAVSigner(signedRAV); } /** - * @dev Computes the hash of a ReceiptAggregateVoucher (RAV). - * @param rav The RAV for which to compute the hash. - * @return The hash of the RAV. + * @notice See {ITAPCollector.encodeRAV} */ - function encodeRAV(ReceiptAggregateVoucher calldata rav) public view returns (bytes32) { + function encodeRAV(ReceiptAggregateVoucher calldata rav) external view returns (bytes32) { return _encodeRAV(rav); } + /** + * @notice See {ITAPCollector.recoverRAVSigner} + */ function _recoverRAVSigner(SignedRAV memory _signedRAV) private view returns (address) { bytes32 messageHash = _encodeRAV(_signedRAV.rav); return ECDSA.recover(messageHash, _signedRAV.signature); } + /** + * @notice See {ITAPCollector.encodeRAV} + */ function _encodeRAV(ReceiptAggregateVoucher memory _rav) private view returns (bytes32) { return _hashTypedDataV4( From 289772e49dbf4f4352bfab8f136dfcd4bac852cb Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 31 May 2024 18:11:12 -0300 Subject: [PATCH 092/277] fix: update GraphEscrow to EscrowPayments --- packages/horizon/test/GraphBase.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 565080cc9..699880050 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -67,7 +67,7 @@ abstract contract GraphBaseTest is Test, Constants { vm.label({ account: address(controller), newLabel: "Controller" }); vm.label({ account: address(token), newLabel: "GraphToken" }); vm.label({ account: address(payments), newLabel: "GraphPayments" }); - vm.label({ account: address(escrow), newLabel: "GraphEscrow" }); + vm.label({ account: address(escrow), newLabel: "PaymentsEscrow" }); vm.label({ account: address(staking), newLabel: "HorizonStaking" }); vm.label({ account: address(stakingExtension), newLabel: "HorizonStakingExtension" }); } @@ -97,7 +97,7 @@ abstract contract GraphBaseTest is Test, Constants { // GraphEscrow predict address bytes32 saltEscrow = keccak256("GraphEscrowSalt"); bytes32 escrowHash = keccak256(bytes.concat( - vm.getCode("GraphEscrow.sol:GraphEscrow"), + vm.getCode("PaymentsEscrow.sol:PaymentsEscrow"), abi.encode( address(controller), revokeCollectorThawingPeriod, From 685f457dd2d7d318591f57661562c9e0ca7c453a Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Mon, 3 Jun 2024 11:30:12 -0300 Subject: [PATCH 093/277] fix: unit tests --- packages/horizon/test/escrow/thaw.t.sol | 16 +++++++++++++--- .../test/staking/delegation/delegate.t.sol | 6 +++--- .../test/staking/delegation/undelegate.t.sol | 2 +- .../test/staking/provision/provision.t.sol | 8 ++++++-- .../test/staking/provision/reprovision.t.sol | 6 +++++- .../horizon/test/staking/stake/unstake.t.sol | 12 ++++++++++-- packages/horizon/test/staking/thaw/thaw.t.sol | 2 +- 7 files changed, 39 insertions(+), 13 deletions(-) diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 110d262e3..1b952e1f1 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -18,17 +18,27 @@ contract GraphEscrowThawTest is GraphEscrowTest { function testThaw_RevertWhen_InsufficientThawAmount( uint256 amount ) public useGateway useDeposit(amount) { - bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInsufficientTokensThawing()"); + bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowNotThawing()"); vm.expectRevert(expectedError); escrow.thaw(users.indexer, 0); } function testThaw_RevertWhen_InsufficientAmount( - uint256 amount + uint256 amount, + uint256 overAmount ) public useGateway useDeposit(amount) { - uint256 overAmount = amount + 1; + overAmount = bound(overAmount, amount + 1, type(uint256).max); bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInsufficientBalance(uint256,uint256)", amount, overAmount); vm.expectRevert(expectedError); escrow.thaw(users.indexer, overAmount); } + + function testThaw_CancelRequest(uint256 amount) public useGateway useDeposit(amount) { + escrow.thaw(users.indexer, amount); + escrow.thaw(users.indexer, 0); + + (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.indexer); + assertEq(amountThawing, 0); + assertEq(thawEndTimestamp, 0); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 603020ef7..58ae6f1e5 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -32,9 +32,9 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { delegationAmount = bound(delegationAmount, 1, MIN_DELEGATION - 1); token.approve(address(staking), delegationAmount); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokens(uint256,uint256)", - MIN_DELEGATION, - delegationAmount + "HorizonStakingInsufficientTokens(uint256,uint256)", + delegationAmount, + MIN_DELEGATION ); vm.expectRevert(expectedError); staking.delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 5c6bab44c..5eca15326 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -49,7 +49,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { vm.assume(overDelegationShares > delegation.shares); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInvalidSharesAmount(uint256,uint256)", + "HorizonStakingInsufficientShares(uint256,uint256)", delegation.shares, overDelegationShares ); diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index f92f85be1..bb5f4792a 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -19,7 +19,7 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { function testProvision_RevertWhen_InsufficientTokens(uint256 amount) public useIndexer useStake(1000 ether) { amount = bound(amount, 0, MIN_PROVISION_SIZE - 1); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInvalidTokens(uint256,uint256)", + "HorizonStakingInsufficientTokens(uint256,uint256)", amount, MIN_PROVISION_SIZE ); @@ -63,7 +63,11 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { ) public useIndexer useStake(amount) { vm.assume(amount > MIN_PROVISION_SIZE); vm.assume(provisionTokens > amount); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientIdleStake(uint256,uint256)", + provisionTokens, + amount + ); vm.expectRevert(expectedError); staking.provision(users.indexer, subgraphDataServiceAddress, provisionTokens, 0, 0); } diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 9cd0c2116..06c033888 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -106,7 +106,11 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientIdleStake(uint256,uint256)", + provisionAmount, + 0 + ); vm.expectRevert(expectedError); _reprovision(provisionAmount, 0); } diff --git a/packages/horizon/test/staking/stake/unstake.t.sol b/packages/horizon/test/staking/stake/unstake.t.sol index 8acd695fe..56eac4bfb 100644 --- a/packages/horizon/test/staking/stake/unstake.t.sol +++ b/packages/horizon/test/staking/stake/unstake.t.sol @@ -50,7 +50,11 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientIdleStake(uint256,uint256)", + amount, + 0 + ); vm.expectRevert(expectedError); staking.unstake(amount); } @@ -67,7 +71,11 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { { skip(thawingPeriod + 1); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientCapacity()"); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingInsufficientIdleStake(uint256,uint256)", + amount, + 0 + ); vm.expectRevert(expectedError); staking.unstake(amount); } diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index 94785421f..713bdaa51 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -78,7 +78,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { ) public useIndexer useProvision(amount, 0, thawingPeriod) { vm.assume(thawAmount > amount); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokensAvailable(uint256,uint256)", + "HorizonStakingInsufficientTokens(uint256,uint256)", amount, thawAmount ); From a83e8877b39b289a2d55bf856c70cdb880600afc Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Mon, 3 Jun 2024 11:32:13 -0300 Subject: [PATCH 094/277] fix: remove commented code --- packages/horizon/test/staking/thaw/thaw.t.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index 713bdaa51..6a4a475f0 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -91,8 +91,6 @@ contract HorizonStakingThawTest is HorizonStakingTest { uint64 thawingPeriod, uint256 thawAmount ) public useIndexer useProvision(amount, 0, thawingPeriod) { - // vm.assume(thawAmount > 0); - // vm.assume(amount / (MAX_THAW_REQUESTS + 1) > thawAmount); thawAmount = bound(thawAmount, 1, amount / (MAX_THAW_REQUESTS + 1)); for (uint256 i = 0; i < 100; i++) { From 273311231d75646a06028f38cf0eab778309f2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 3 Jun 2024 15:26:23 -0300 Subject: [PATCH 095/277] docs: finalize natspec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/GraphDirectory.sol | 21 +- .../data-service/interfaces/IDataService.sol | 8 +- .../utilities/ProvisionManager.sol | 36 +++ .../internal/IHorizonStakingMain.sol | 3 + .../contracts/DisputeManager.sol | 118 ++++---- .../contracts/DisputeManagerStorage.sol | 20 +- .../contracts/SubgraphService.sol | 265 ++++++++++++++++-- .../contracts/SubgraphServiceStorage.sol | 3 +- .../contracts/interfaces/IDisputeManager.sol | 42 ++- .../contracts/interfaces/ISubgraphService.sol | 120 +++++++- .../contracts/libraries/Allocation.sol | 98 ++++++- .../contracts/libraries/Attestation.sol | 10 +- .../contracts/libraries/LegacyAllocation.sol | 57 +++- .../contracts/utilities/AllocationManager.sol | 204 ++++++++++++-- .../utilities/AllocationManagerStorage.sol | 11 +- .../utilities/AttestationManager.sol | 19 ++ .../utilities/AttestationManagerStorage.sol | 1 + .../contracts/utilities/Directory.sol | 50 ++++ 18 files changed, 944 insertions(+), 142 deletions(-) diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/data-service/GraphDirectory.sol index ffa1c08ad..085ee8a8b 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/data-service/GraphDirectory.sol @@ -26,36 +26,36 @@ import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration abstract contract GraphDirectory { // -- Graph Horizon contracts -- - /// @dev The Graph Token contract address + /// @notice The Graph Token contract address IGraphToken private immutable GRAPH_TOKEN; - /// @dev The Horizon Staking contract address + /// @notice The Horizon Staking contract address IHorizonStaking private immutable GRAPH_STAKING; - /// @dev The Graph Payments contract address + /// @notice The Graph Payments contract address IGraphPayments private immutable GRAPH_PAYMENTS; - /// @dev The Payments Escrow contract address + /// @notice The Payments Escrow contract address IPaymentsEscrow private immutable GRAPH_PAYMENTS_ESCROW; // -- Graph periphery contracts -- - /// @dev The Graph Controller contract address + /// @notice The Graph Controller contract address IController private immutable GRAPH_CONTROLLER; - /// @dev The Epoch Manager contract address + /// @notice The Epoch Manager contract address IEpochManager private immutable GRAPH_EPOCH_MANAGER; - /// @dev The Rewards Manager contract address + /// @notice The Rewards Manager contract address IRewardsManager private immutable GRAPH_REWARDS_MANAGER; - /// @dev The Token Gateway contract address + /// @notice The Token Gateway contract address ITokenGateway private immutable GRAPH_TOKEN_GATEWAY; - /// @dev The Bridge Escrow contract address + /// @notice The Bridge Escrow contract address IBridgeEscrow private immutable GRAPH_BRIDGE_ESCROW; - /// @dev The Graph Proxy Admin contract address + /// @notice The Graph Proxy Admin contract address IGraphProxyAdmin private immutable GRAPH_PROXY_ADMIN; // -- Legacy Graph contracts -- @@ -104,6 +104,7 @@ abstract contract GraphDirectory { * - `controller` cannot be zero address * * Emits a {GraphDirectoryInitialized} event + * * @param controller The address of the Graph Controller contract. */ constructor(address controller) { diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index aa3ef3dfa..f2ffec1a5 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -68,8 +68,7 @@ interface IDataService { * @dev Before registering, the service provider must have created a provision in the * Graph Horizon staking contract with parameters that are compatible with the data service. * - * Verifies the provision parameters and marks it as accepted it in the Graph Horizon - * staking contract using {_acceptProvision}. + * Verifies provision parameters and rejects registration in the event they are not valid. * * Emits a {ServiceProviderRegistered} event. * @@ -82,10 +81,9 @@ interface IDataService { function register(address serviceProvider, bytes calldata data) external; /** - * @notice Accepts the provision of a service provider in the {Graph Horizon staking + * @notice Accepts staged parameters in the provision of a service provider in the {Graph Horizon staking * contract}. - * @dev Provides a way for the data service to revalidate and reaccept a provision that - * had a parameter change. Should call {_acceptProvision}. + * @dev Provides a way for the data service to validate and accept provision parameter changes. Call {_acceptProvision}. * * Emits a {ProvisionAccepted} event. * diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index ff02978fb..520b7a24b 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -96,6 +96,42 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa _; } + /** + * @notice External getter for the thawing period range + * @return Minimum thawing period allowed + * @return Maximum thawing period allowed + */ + function getThawingPeriodRange() external view returns (uint64, uint64) { + return _getThawingPeriodRange(); + } + + /** + * @notice External getter for the verifier cut range + * @return Minimum verifier cut allowed + * @return Maximum verifier cut allowed + */ + function getVerifierCutRange() external view returns (uint32, uint32) { + return _getVerifierCutRange(); + } + + /** + * @notice External getter for the provision tokens range + * @return Minimum provision tokens allowed + * @return Maximum provision tokens allowed + */ + function getProvisionTokensRange() external view returns (uint256, uint256) { + return _getProvisionTokensRange(); + } + + /** + * @notice External getter for the delegation ratio range + * @return Minimum delegation ratio allowed + * @return Maximum delegation ratio allowed + */ + function getDelegationRatioRange() external view returns (uint32, uint32) { + return _getDelegationRatioRange(); + } + /** * @notice Initializes the contract and any parent contracts. */ diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 33a8f29cc..201e1b75a 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -767,6 +767,9 @@ interface IHorizonStakingMain { * the provider has provisioned stake, and up to the amount of tokens they have provisioned. * If the service provider's stake is not enough, the associated delegation pool might be slashed * depending on the value of the global delegation slashing flag. + * + * Part of the slashed tokens are sent to the `verifierDestination` as a reward. + * * @dev Requirements: * - `tokens` must be less than or equal to the amount of tokens provisioned by the service provider. * - `tokensVerifier` must be less than the provision's tokens times the provision's maximum verifier cut. diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index e85fb54d7..765d08fbc 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -20,8 +20,7 @@ import { AttestationManager } from "./utilities/AttestationManager.sol"; /* * @title DisputeManager - * @notice Provides a way to align the incentives of participants by having slashing as deterrent - * for incorrect behaviour. + * @notice Provides a way to permissionlessly create disputes for incorrect behavior in the Subgraph Service. * * There are two types of disputes that can be created: Query disputes and Indexing disputes. * @@ -55,13 +54,17 @@ contract DisputeManager is // -- Modifiers -- /** - * @dev Check if the caller is the arbitrator. + * @notice Check if the caller is the arbitrator. */ modifier onlyArbitrator() { require(msg.sender == arbitrator, DisputeManagerNotArbitrator()); _; } + /** + * @notice Check if the dispute exists and is pending. + * @param disputeId The dispute Id + */ modifier onlyPendingDispute(bytes32 disputeId) { require(isDisputeCreated(disputeId), DisputeManagerInvalidDispute(disputeId)); require( @@ -71,18 +74,26 @@ contract DisputeManager is _; } + /** + * @notice Check if the caller is the fisherman of the dispute. + * @param disputeId The dispute Id + */ modifier onlyFisherman(bytes32 disputeId) { require(isDisputeCreated(disputeId), DisputeManagerInvalidDispute(disputeId)); require(msg.sender == disputes[disputeId].fisherman, DisputeManagerNotFisherman()); _; } + /** + * @notice Contract constructor + * @param controller Address of the controller + */ constructor(address controller) GraphDirectory(controller) { _disableInitializers(); } /** - * @dev Initialize this contract. + * @notice Initialize this contract. * @param arbitrator Arbitrator role * @param disputePeriod Dispute period in seconds * @param minimumDeposit Minimum deposit required to create a Dispute @@ -107,7 +118,7 @@ contract DisputeManager is } /** - * @dev Create an indexing dispute for the arbitrator to resolve. + * @notice Create an indexing dispute for the arbitrator to resolve. * 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. @@ -123,7 +134,7 @@ contract DisputeManager is } /** - * @dev Create a query dispute for the arbitrator to resolve. + * @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 @@ -144,7 +155,7 @@ contract DisputeManager is } /** - * @dev Create query disputes for two conflicting attestations. + * @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 @@ -194,11 +205,11 @@ contract DisputeManager is } /** - * @dev The arbitrator accepts a dispute as being valid. + * @notice The arbitrator accepts a dispute as being valid. * 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` + * @dev Accept a dispute with Id `disputeId` * @param disputeId Id of the dispute to be accepted * @param tokensSlash Amount of tokens to slash from the indexer */ @@ -225,8 +236,8 @@ contract DisputeManager is } /** - * @dev The arbitrator draws dispute. - * @notice Ignore a dispute with Id `disputeId` + * @notice The arbitrator draws dispute. + * @dev Ignore a dispute with Id `disputeId` * @param disputeId Id of the dispute to be disregarded */ function drawDispute(bytes32 disputeId) external override onlyArbitrator onlyPendingDispute(disputeId) { @@ -245,9 +256,9 @@ contract DisputeManager is } /** - * @dev Once the dispute period ends, if the disput status remains Pending, + * @notice Once the dispute period ends, if the disput status remains Pending, * the fisherman can cancel the dispute and get back their initial deposit. - * @notice Cancel a dispute with Id `disputeId` + * @dev Cancel a dispute with Id `disputeId` * @param disputeId Id of the dispute to be cancelled */ function cancelDispute(bytes32 disputeId) external override onlyFisherman(disputeId) onlyPendingDispute(disputeId) { @@ -267,8 +278,8 @@ contract DisputeManager is } /** - * @dev Set the arbitrator address. - * @notice Update the arbitrator to `_arbitrator` + * @notice Set the arbitrator address. + * @dev Update the arbitrator to `_arbitrator` * @param arbitrator The address of the arbitration contract or party */ function setArbitrator(address arbitrator) external override onlyOwner { @@ -276,8 +287,8 @@ contract DisputeManager is } /** - * @dev Set the dispute period. - * @notice Update the dispute period to `_disputePeriod` in seconds + * @notice Set the dispute period. + * @dev Update the dispute period to `_disputePeriod` in seconds * @param disputePeriod Dispute period in seconds */ function setDisputePeriod(uint64 disputePeriod) external override onlyOwner { @@ -285,8 +296,8 @@ contract DisputeManager is } /** - * @dev Set the minimum deposit required to create a dispute. - * @notice Update the minimum deposit to `_minimumDeposit` Graph Tokens + * @notice Set the minimum deposit required to create a dispute. + * @dev Update the minimum deposit to `_minimumDeposit` Graph Tokens * @param minimumDeposit The minimum deposit in Graph Tokens */ function setMinimumDeposit(uint256 minimumDeposit) external override onlyOwner { @@ -294,8 +305,8 @@ contract DisputeManager is } /** - * @dev 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. + * @dev Update the reward percentage to `_percentage` * @param fishermanRewardCut_ Reward as a percentage of indexer stake */ function setFishermanRewardCut(uint32 fishermanRewardCut_) external override onlyOwner { @@ -303,7 +314,7 @@ contract DisputeManager is } /** - * @dev Set the maximum percentage that can be used for slashing indexers. + * @notice Set the maximum percentage that can be used for slashing indexers. * @param maxSlashingCut_ Max percentage slashing for disputes */ function setMaxSlashingCut(uint32 maxSlashingCut_) external override onlyOwner { @@ -311,8 +322,8 @@ contract DisputeManager is } /** - * @dev Set the subgraph service address. - * @notice Update the subgraph service to `_subgraphService` + * @notice Set the subgraph service address. + * @dev Update the subgraph service to `_subgraphService` * @param subgraphService The address of the subgraph service contract */ function setSubgraphService(address subgraphService) external override onlyOwner { @@ -320,10 +331,10 @@ contract DisputeManager is } /** - * @dev Get the message hash that a indexer used to sign the receipt. + * @notice Get the message hash that a indexer used to sign the receipt. * 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 + * @dev 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 */ @@ -332,7 +343,7 @@ contract DisputeManager is } /** - * @dev Get the verifier cut. + * @notice Get the verifier cut. * @return Verifier cut in percentage (ppm) */ function getVerifierCut() external view override returns (uint32) { @@ -340,13 +351,18 @@ contract DisputeManager is } /** - * @dev Get the dispute period. + * @notice Get the dispute period. * @return Dispute period in seconds */ function getDisputePeriod() external view override returns (uint64) { return disputePeriod; } + /** + * @notice Checks if two attestations are conflicting. + * @param attestation1 The first attestation + * @param attestation2 The second attestation + */ function areConflictingAttestations( Attestation.State memory attestation1, Attestation.State memory attestation2 @@ -355,8 +371,8 @@ contract DisputeManager is } /** - * @dev The arbitrator rejects a dispute as being invalid. - * @notice Reject a dispute with Id `disputeId` + * @notice The arbitrator rejects a dispute as being invalid. + * @dev Reject a dispute with Id `disputeId` * @param disputeId Id of the dispute to be rejected */ function rejectDispute(bytes32 disputeId) public override onlyArbitrator onlyPendingDispute(disputeId) { @@ -378,7 +394,7 @@ contract DisputeManager is } /** - * @dev Returns the indexer that signed an attestation. + * @notice Returns the indexer that signed an attestation. * @param attestation Attestation * @return indexer address */ @@ -396,8 +412,8 @@ contract DisputeManager is } /** - * @dev Return whether a dispute exists or not. - * @notice Return if dispute with Id `disputeId` exists + * @notice Return whether a dispute exists or not. + * @dev Return if dispute with Id `disputeId` exists * @param disputeId True if dispute already exists */ function isDisputeCreated(bytes32 disputeId) public view override returns (bool) { @@ -405,7 +421,7 @@ contract DisputeManager is } /** - * @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 @@ -466,7 +482,7 @@ contract DisputeManager is } /** - * @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 @@ -508,7 +524,7 @@ contract DisputeManager is } /** - * @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 */ @@ -523,7 +539,7 @@ contract DisputeManager is } /** - * @dev Cancel the conflicting dispute if there is any for the one passed to this function. + * @notice Cancel the conflicting dispute if there is any for the one passed to this function. * @param _dispute Dispute * @return True if cancelled */ @@ -538,7 +554,7 @@ contract DisputeManager is } /** - * @dev Pull deposit from submitter account. + * @notice Pull deposit from submitter account. * @param _deposit Amount of tokens to deposit */ function _pullSubmitterDeposit(uint256 _deposit) private { @@ -550,7 +566,7 @@ contract DisputeManager is } /** - * @dev Make the subgraph service contract slash the indexer and reward the challenger. + * @notice Make the subgraph service 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 _tokensSlash Amount of tokens to slash from the indexer @@ -578,8 +594,8 @@ contract DisputeManager is } /** - * @dev Internal: Set the arbitrator address. - * @notice Update the arbitrator to `_arbitrator` + * @notice Internal: Set the arbitrator address. + * @dev Update the arbitrator to `_arbitrator` * @param _arbitrator The address of the arbitration contract or party */ function _setArbitrator(address _arbitrator) private { @@ -589,8 +605,8 @@ contract DisputeManager is } /** - * @dev Internal: Set the dispute period. - * @notice Update the dispute period to `_disputePeriod` in seconds + * @notice Internal: Set the dispute period. + * @dev Update the dispute period to `_disputePeriod` in seconds * @param _disputePeriod Dispute period in seconds */ function _setDisputePeriod(uint64 _disputePeriod) private { @@ -600,8 +616,8 @@ contract DisputeManager is } /** - * @dev Internal: Set the minimum deposit required to create a dispute. - * @notice Update the minimum deposit to `_minimumDeposit` Graph Tokens + * @notice Internal: Set the minimum deposit required to create a dispute. + * @dev Update the minimum deposit to `_minimumDeposit` Graph Tokens * @param _minimumDeposit The minimum deposit in Graph Tokens */ function _setMinimumDeposit(uint256 _minimumDeposit) private { @@ -611,8 +627,8 @@ contract DisputeManager is } /** - * @dev Internal: Set the percent reward that the fisherman gets when slashing occurs. - * @notice Update the reward percentage to `_percentage` + * @notice Internal: Set the percent reward that the fisherman gets when slashing occurs. + * @dev Update the reward percentage to `_percentage` * @param _fishermanRewardCut Reward as a percentage of indexer stake */ function _setFishermanRewardCut(uint32 _fishermanRewardCut) private { @@ -623,7 +639,7 @@ contract DisputeManager is } /** - * @dev Internal: Set the maximum percentage that can be used for slashing indexers. + * @notice Internal: Set the maximum percentage that can be used for slashing indexers. * @param _maxSlashingCut Max percentage slashing for disputes */ function _setMaxSlashingCut(uint32 _maxSlashingCut) private { @@ -634,8 +650,8 @@ contract DisputeManager is } /** - * @dev Internal: Set the subgraph service address. - * @notice Update the subgraph service to `_subgraphService` + * @notice Internal: Set the subgraph service address. + * @dev Update the subgraph service to `_subgraphService` * @param _subgraphService The address of the subgraph service contract */ function _setSubgraphService(address _subgraphService) private { @@ -645,7 +661,7 @@ contract DisputeManager is } /** - * @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 */ diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol index bf2b368d6..19e217f12 100644 --- a/packages/subgraph-service/contracts/DisputeManagerStorage.sol +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -6,28 +6,24 @@ import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; abstract contract DisputeManagerV1Storage { - // -- State -- - + /// @notice The Subgraph Service contract address ISubgraphService public subgraphService; - // The arbitrator is solely in control of arbitrating disputes + /// @notice The arbitrator is solely in control of arbitrating disputes address public arbitrator; - // dispute period in seconds + /// @notice dispute period in seconds uint64 public disputePeriod; - // Minimum deposit required to create a Dispute + /// @notice Minimum deposit required to create a Dispute uint256 public minimumDeposit; - // 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. In PPM. uint32 public fishermanRewardCut; - // Maximum percentage of indexer stake that can be slashed on a dispute - // Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%) + /// @notice Maximum percentage of indexer stake that can be slashed on a dispute. In PPM. uint32 public maxSlashingCut; - // Disputes created : disputeID => Dispute - // disputeID - check creation functions to see how disputeID is built - mapping(bytes32 disputeID => IDisputeManager.Dispute dispute) public disputes; + /// @notice List of disputes created + mapping(bytes32 disputeId => IDisputeManager.Dispute dispute) public disputes; } diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index f39beed4c..f6fa952e5 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -10,7 +10,6 @@ import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/O import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { DataServicePausableUpgradeable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol"; import { DataService } from "@graphprotocol/horizon/contracts/data-service/DataService.sol"; -import { DataServiceRescuable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServiceRescuable.sol"; import { DataServiceFees } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServiceFees.sol"; import { Directory } from "./utilities/Directory.sol"; import { AllocationManager } from "./utilities/AllocationManager.sol"; @@ -20,13 +19,11 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; -// TODO: contract needs to be upgradeable contract SubgraphService is Initializable, OwnableUpgradeable, DataService, DataServicePausableUpgradeable, - DataServiceRescuable, DataServiceFees, Directory, AllocationManager, @@ -37,13 +34,25 @@ contract SubgraphService is using PPMMath for uint256; using Allocation for mapping(address => Allocation.State); + /** + * @notice Checks that an indexer is registered + * @param indexer The address of the indexer + */ modifier onlyRegisteredIndexer(address indexer) { require(indexers[indexer].registeredAt != 0, SubgraphServiceIndexerNotRegistered(indexer)); _; } /** - * @dev Strict delegation ratio not enforced. + * @notice Checks that a provision is valid + * @dev A valid provision is defined as one that: + * - has at least the minimum amount of tokens requiered by the subgraph service + * - has a thawing period at least equal to {DisputeManager.disputePeriod} + * - has a verifier cut at most equal to {DisputeManager.verifierCut} + * + * Note that no delegation ratio is enforced here. + * + * @param indexer The address of the indexer */ modifier onlyValidProvision(address indexer) override { _checkProvisionTokens(indexer); @@ -51,15 +60,28 @@ contract SubgraphService is _; } + /** + * @notice Constructor for the SubgraphService contract + * @dev DataService and Directory constructors set a bunch of immutable variables + * @param graphController The address of the Graph Controller contract + * @param disputeManager The address of the DisputeManager contract + * @param tapCollector The address of the TAPCollector contract + * @param curation The address of the Curation contract + */ constructor( address graphController, address disputeManager, - address tapVerifier, + address tapCollector, address curation - ) DataService(graphController) Directory(address(this), tapVerifier, disputeManager, curation) { + ) DataService(graphController) Directory(address(this), tapCollector, disputeManager, curation) { _disableInitializers(); } + /** + * @notice See {ISubgraphService.initialize} + * @dev The thawingPeriod and verifierCut ranges are not set here because they are variables + * on the DisputeManager. We use the {ProvisionManager} overrideable getters to get the ranges. + */ function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external override initializer { __Ownable_init(msg.sender); __DataService_init(); @@ -70,6 +92,24 @@ contract SubgraphService is _setDelegationRatioRange(type(uint32).min, maximumDelegationRatio); } + /** + * @notice + * @dev Implements {IDataService.register} + * + * Requirements: + * - The indexer must not be already registered + * - The URL must not be empty + * - The provision must be valid according to the subgraph service rules + * + * Emits a {ServiceProviderRegistered} event + * + * @param indexer The address of the indexer to register + * @param data Encoded registration data: + * - address `url`: The URL of the indexer + * - string `geohash`: The geohash of the indexer + * - address `rewardsDestination`: The address where the indexer wants to receive indexing rewards. + * Use zero address for automatic reprovisioning to the subgraph service. + */ function register( address indexer, bytes calldata data @@ -91,6 +131,19 @@ contract SubgraphService is emit ServiceProviderRegistered(indexer); } + /** + * @notice Accept staged parameters in the provision of a service provider + * @dev Implements {IDataService-acceptProvision} + * + * Requirements: + * - The indexer must be registered + * - Must have previously staged provision parameters, using {IHorizonStaking-setProvisionParameters} + * - The new provision parameters must be valid according to the subgraph service rules + * + * Emits a {ProvisionAccepted} event + * + * @param indexer The address of the indexer to accept the provision for + */ function acceptProvision( address indexer, bytes calldata @@ -100,6 +153,30 @@ contract SubgraphService is emit ProvisionAccepted(indexer); } + /** + * @notice Allocates tokens to subgraph deployment, manifesting the indexer's commitment to index it + * @dev This is the equivalent of the `allocate` function in the legacy Staking contract. + * + * Requirements: + * - The indexer must be registered + * - The provision must be valid according to the subgraph service rules + * - Allocation id cannot be zero + * - Allocation id cannot be reused from the legacy staking contract + * - The indexer must have enough available tokens to allocate + * + * The `allocationProof` is a 65-bytes Ethereum signed message of `keccak256(indexerAddress,allocationId)`. + * + * See {AllocationManager-allocate} for more details. + * + * Emits {ServiceStarted} and {AllocationCreated} events + * + * @param indexer The address of the indexer + * @param data Encoded data: + * - bytes32 `subgraphDeploymentId`: The id of the subgraph deployment + * - uint256 `tokens`: The amount of tokens to allocate + * - address `allocationId`: The id of the allocation + * - bytes `allocationProof`: Signed proof of the allocation id address ownership + */ function startService( address indexer, bytes calldata data @@ -119,6 +196,25 @@ contract SubgraphService is emit ServiceStarted(indexer); } + /** + * @notice Close an allocation, indicating that the indexer has stopped indexing the subgraph deployment + * @dev This is the equivalent of the `closeAllocation` function in the legacy Staking contract. + * There are a few notable differences with the legacy function: + * - allocations are nowlong lived. All service payments, including indexing rewards, should be collected periodically + * without the need of closing the allocation. Allocations should only be closed when indexers want to reclaim the allocated + * tokens for other purposes. + * - No POI is required to close an allocation. Indexers should present POIs to collect indexing rewards using {collect}. + * + * Requirements: + * - The indexer must be registered + * - Allocation must exist and be open + * + * Emits {ServiceStopped} and {AllocationClosed} events + * + * @param indexer The address of the indexer + * @param data Encoded data: + * - address `allocationId`: The id of the allocation + */ function stopService( address indexer, bytes calldata data @@ -128,20 +224,27 @@ contract SubgraphService is emit ServiceStopped(indexer); } - function resizeAllocation( - address indexer, - address allocationId, - uint256 tokens - ) - external - onlyProvisionAuthorized(indexer) - onlyValidProvision(indexer) - onlyRegisteredIndexer(indexer) - whenNotPaused - { - _resizeAllocation(allocationId, tokens, maximumDelegationRatio); - } - + /** + * @notice Collects payment for the service provided by the indexer + * Allows collecting different types of payments such as query fees and indexing rewards. + * It uses Graph Horizon payments protocol to process payments. + * Reverts if the payment type is not supported. + * @dev This function is the equivalent of the `collect` function for query fees and the `closeAllocation` function + * for indexing rewards in the legacy Staking contract. + * + * Requirements: + * - The indexer must be registered + * - The provision must be valid according to the subgraph service rules + * + * Emits a {ServicePaymentCollected} event. Emits payment type specific events. + * + * For query fees, see {SubgraphService-_collectQueryFees} for more details. + * For indexing rewards, see {AllocationManager-_collectIndexingRewards} for more details. + * + * @param indexer The address of the indexer + * @param paymentType The type of payment to collect as defined in {IGraphPayments} + * @param data Encoded data to fulfill the payment. The structure of the data depends on the payment type. See above. + */ function collect( address indexer, IGraphPayments.PaymentTypes paymentType, @@ -160,12 +263,46 @@ contract SubgraphService is emit ServicePaymentCollected(indexer, paymentType, paymentCollected); } + /** + * @notice Slash an indexer + * @dev Slashing is delegated to the {DisputeManager} contract which is the only one that can call this + * function. + * + * See {IHorizonStaking-slash} for more details. + * + * Emits a {ServiceProviderSlashed} event. + * + * @param indexer The address of the indexer to be slashed + * @param data Encoded data: + * - uint256 `tokens`: The amount of tokens to slash + * - uint256 `reward`: The amount of tokens to reward the slasher + */ function slash(address indexer, bytes calldata data) external override onlyDisputeManager whenNotPaused { (uint256 tokens, uint256 reward) = abi.decode(data, (uint256, uint256)); _graphStaking().slash(indexer, tokens, reward, address(_disputeManager())); emit ServiceProviderSlashed(indexer, tokens); } + /** + * @notice See {ISubgraphService.resizeAllocation} + */ + function resizeAllocation( + address indexer, + address allocationId, + uint256 tokens + ) + external + onlyProvisionAuthorized(indexer) + onlyValidProvision(indexer) + onlyRegisteredIndexer(indexer) + whenNotPaused + { + _resizeAllocation(allocationId, tokens, maximumDelegationRatio); + } + + /** + * @notice See {ISubgraphService.migrateLegacyAllocation} + */ function migrateLegacyAllocation( address indexer, address allocationId, @@ -174,14 +311,55 @@ contract SubgraphService is _migrateLegacyAllocation(indexer, allocationId, subgraphDeploymentID); } + /** + * @notice See {ISubgraphService.setPauseGuardian} + */ function setPauseGuardian(address pauseGuardian, bool allowed) external override onlyOwner { _setPauseGuardian(pauseGuardian, allowed); } + /** + * @notice See {ISubgraphService.setRewardsDestination} + */ + function setRewardsDestination(address rewardsDestination) external { + _setRewardsDestination(msg.sender, rewardsDestination); + } + + /** + * @notice See {ISubgraphService.setMinimumProvisionTokens} + */ + function setMinimumProvisionTokens(uint256 minimumProvisionTokens) external override onlyOwner { + _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); + } + + /** + * @notice See {ISubgraphService.setMaximumDelegationRatio} + */ + function setMaximumDelegationRatio(uint32 maximumDelegationRatio) external override onlyOwner { + _setDelegationRatioRange(type(uint32).min, maximumDelegationRatio); + } + + /** + * @notice See {ISubgraphService.getAllocation} + */ function getAllocation(address allocationId) external view override returns (Allocation.State memory) { return allocations[allocationId]; } + /** + * @notice Get allocation data to calculate rewards issuance + * @dev Implements {IRewardsIssuer.getAllocationData} + * @dev Note that this is slightly different than {getAllocation}. It returns an + * unstructured subset of the allocation data, which is the minimum required to mint rewards. + * + * Should only be used by the {RewardsManager}. + * + * @param allocationId The allocation Id + * @return indexer The indexer address + * @return subgraphDeploymentId Subgraph deployment id for the allocation + * @return tokens Amount of allocated tokens + * @return accRewardsPerAllocatedToken Rewards snapshot + */ function getAllocationData( address allocationId ) external view override returns (address, bytes32, uint256, uint256) { @@ -194,25 +372,67 @@ contract SubgraphService is ); } + /** + * @notice See {ISubgraphService.getLegacyAllocation} + */ function getLegacyAllocation(address allocationId) external view override returns (LegacyAllocation.State memory) { return legacyAllocations[allocationId]; } + /** + * @notice See {ISubgraphService.encodeAllocationProof} + */ function encodeAllocationProof(address indexer, address allocationId) external view override returns (bytes32) { return _encodeAllocationProof(indexer, allocationId); } // -- Data service parameter getters -- + /** + * @notice Getter for the accepted thawing period range for provisions + * @dev This override ensures {ProvisionManager} uses the thawing period from the {DisputeManager} + * @return min The minimum thawing period which is defined by {DisputeManager-getDisputePeriod} + * @return max The maximum is unbounded + */ function _getThawingPeriodRange() internal view override returns (uint64 min, uint64 max) { uint64 disputePeriod = _disputeManager().getDisputePeriod(); return (disputePeriod, type(uint64).max); } + /** + * @notice Getter for the accepted verifier cut range for provisions + * @return min The minimum verifier cut which is defined by {DisputeManager-getVerifierCut} + * @return max The maximum is unbounded + */ function _getVerifierCutRange() internal view override returns (uint32 min, uint32 max) { uint32 verifierCut = _disputeManager().getVerifierCut(); return (verifierCut, type(uint32).max); } + /** + * @notice Collect query fees + * Stake equal to the amount being collected times the `stakeToFeesRatio` is locked into a stake claim. + * This claim can be released at a later stage once expired. + * + * It's important to note that before collecting this function will attempt to release any expired stake claims. + * This could lead to an out of gas error if there are too many expired claims. In that case, the indexer will need to + * manually release the claims, see {IDataServiceFees-releaseStake}, before attempting to collect again. + * + * @dev This function is the equivalent of the legacy `collect` function for query fees. + * @dev Uses the {TAPCollector} to collect payment from Graph Horizon payments protocol. + * Fees are distributed to service provider and delegators by {GraphPayments}, though curators + * share is distributed by this function. + * + * Query fees can be collected on closed allocations. + * + * Requirements: + * - Indexer must have enough available tokens to lock as economic security for fees + * + * Emits a {StakeClaimsReleased} event, and a {StakeClaimReleased} event for each claim released. + * Emits a {StakeClaimLocked} event. + * Emits a {QueryFeesCollected} event. + * + * @param _data Encoded data containing a signed RAV + */ function _collectQueryFees(bytes memory _data) private returns (uint256 feesCollected) { ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); address indexer = signedRav.rav.serviceProvider; @@ -264,6 +484,11 @@ contract SubgraphService is return tokensCollected; } + /** + * @notice Gets the payment cuts for query fees + * Checks if the subgraph is curated and adjusts the curation cut accordingly + * @param _subgraphDeploymentId The subgraph deployment id + */ function _getQueryFeePaymentCuts(bytes32 _subgraphDeploymentId) private view returns (PaymentCuts memory) { PaymentCuts memory queryFeePaymentCuts = paymentCuts[IGraphPayments.PaymentTypes.QueryFee]; diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 9d2ae9966..50e72b417 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -8,8 +8,7 @@ abstract contract SubgraphServiceV1Storage { /// @notice Service providers registered in the data service mapping(address indexer => ISubgraphService.Indexer details) public indexers; - // -- Fees -- - // multiplier for how many tokens back collected query fees + ///@notice Multiplier for how many tokens back collected query fees uint256 public stakeToFeesRatio; /// @notice The fees cut taken by the subgraph service diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 27bd0418f..0da818cfa 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -5,14 +5,15 @@ pragma solidity 0.8.26; import { Attestation } from "../libraries/Attestation.sol"; interface IDisputeManager { - // -- Dispute -- + /// @notice Types of disputes that can be created enum DisputeType { Null, IndexingDispute, QueryDispute } + /// @notice Status of a dispute enum DisputeStatus { Null, Accepted, @@ -22,23 +23,58 @@ interface IDisputeManager { Cancelled } - // Disputes contain info necessary for the Arbitrator to verify and resolve + /// @notice Disputes contain info necessary for the Arbitrator to verify and resolve struct Dispute { + // Indexer that is being disputed address indexer; + // Fisherman that created the dispute address fisherman; + // Amount of tokens deposited by the fisherman uint256 deposit; + // Link to a related dispute, used when creating dispute via conflicting attestations bytes32 relatedDisputeId; + // Type of dispute DisputeType disputeType; + // Status of the dispute DisputeStatus status; + // Timestamp when the dispute was created uint256 createdAt; } - // -- Events -- + /** + * @notice Emitted when arbitrator is set. + * @param arbitrator The address of the arbitrator. + */ event ArbitratorSet(address indexed arbitrator); + + /** + * @notice Emitted when dispute period is set. + * @param disputePeriod The dispute period in seconds. + */ event DisputePeriodSet(uint64 disputePeriod); + + /** + * @notice Emitted when minimum deposit is set. + * @param minimumDeposit The minimum deposit required to create a dispute. + */ event MinimumDepositSet(uint256 minimumDeposit); + + /** + * @notice Emitted when max slashing cut is set. + * @param maxSlashingCut The maximum slashing cut that can be set. + */ event MaxSlashingCutSet(uint32 maxSlashingCut); + + /** + * @notice Emitted when fisherman reward cut is set. + * @param fishermanRewardCut The fisherman reward cut. + */ event FishermanRewardCutSet(uint32 fishermanRewardCut); + + /** + * @notice Emitted when subgraph service is set. + * @param subgraphService The address of the subgraph service. + */ event SubgraphServiceSet(address indexed subgraphService); /** diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 868e63fca..d4b51999b 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -7,18 +7,40 @@ import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGra import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; +/** + * @title Interface for the {SubgraphService} contract + * @dev This interface extends {IDataServiceFees} and {IDataService}. + * @notice The Subgraph Service is a data service built on top of Graph Horizon that supports the use case of + * subgraph indexing and querying. The {SubgraphService} contract implements the flows described in the Data + * Service framework to allow indexers to register as subgraph service providers, create allocations to signal + * their commitment to index a subgraph, and collect fees for indexing and querying services. + */ interface ISubgraphService is IDataServiceFees { + /// @notice Contains details for each indexer struct Indexer { + // Timestamp when the indexer registered uint256 registeredAt; + // The URL where the indexer can be reached at for queries string url; + // The indexer's geo location, expressed as a geo hash string geoHash; } + /// @notice Payment cut definitions for each payment type struct PaymentCuts { + // The cut the service provider takes from the payment uint128 serviceCut; + // The cut curators take from the payment uint128 curationCut; } + /** + * @notice Emitted when a subgraph service collects query fees from Graph Payments + * @param serviceProvider The address of the service provider + * @param tokensCollected The amount of tokens collected + * @param tokensCurators The amount of tokens curators receive + * @param tokensSubgraphService The amount of tokens the subgraph service receives + */ event QueryFeesCollected( address indexed serviceProvider, uint256 tokensCollected, @@ -26,22 +48,116 @@ interface ISubgraphService is IDataServiceFees { uint256 tokensSubgraphService ); + /** + * @notice Thrown when an indexer tries to register with an empty URL + */ error SubgraphServiceEmptyUrl(); - error SubgraphServiceInvalidPaymentType(IGraphPayments.PaymentTypes feeType); + + /** + * @notice Thrown when an indexer tries to register but they are already registered + */ error SubgraphServiceIndexerAlreadyRegistered(); + + /** + * @notice Thrown when an indexer tries to perform an operation but they are not registered + * @param indexer The address of the indexer that is not registered + */ error SubgraphServiceIndexerNotRegistered(address indexer); + + /** + * @notice Thrown when an indexer tries to collect fees for an unsupported payment type + * @param paymentType The payment type that is not supported + */ + error SubgraphServiceInvalidPaymentType(IGraphPayments.PaymentTypes paymentType); + + /** + * @notice Thrown when the contract GRT balance is inconsistent with the payment amount collected + * from Graph Payments + * @param balanceBefore The contract GRT balance before the collection + * @param balanceAfter The contract GRT balance after the collection + * @param tokensCollected The amount of tokens collected + */ error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); + /** + * @notice Initialize the contract + * @param minimumProvisionTokens The minimum amount of provisioned tokens required to create an allocation + * @param maximumDelegationRatio The maximum delegation ratio allowed for an allocation + */ function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external; + + /** + * @notice Change the amount of tokens in an allocation + * @dev Requirements: + * - The indexer must be registered + * - The provision must be valid according to the subgraph service rules + * - `tokens` must be different from the current allocation size + * - The indexer must have enough available tokens to allocate if they are upsizing the allocation + * + * Emits a {AllocationResized} event. + * + * See {AllocationManager-_resizeAllocation} for more details. + * + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + * @param tokens The new amount of tokens in the allocation + */ function resizeAllocation(address indexer, address allocationId, uint256 tokens) external; - function migrateLegacyAllocation(address indexer, address allocationId, bytes32 subgraphDeploymentID) external; + /** + * @notice Imports a legacy allocation id into the subgraph service + * This is a governor only action that is required to prevent indexers from re-using allocation ids from the + * legacy staking contract. + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + * @param subgraphDeploymentId The id of the subgraph deployment + */ + function migrateLegacyAllocation(address indexer, address allocationId, bytes32 subgraphDeploymentId) external; + /** + * @notice Sets a pause guardian + * @param pauseGuardian The address of the pause guardian + * @param allowed True if the pause guardian is allowed to pause the contract, false otherwise + */ function setPauseGuardian(address pauseGuardian, bool allowed) external; + /** + * @notice Sets the minimum amount of provisioned tokens required to create an allocation + * @param minimumProvisionTokens The minimum amount of provisioned tokens required to create an allocation + */ + function setMinimumProvisionTokens(uint256 minimumProvisionTokens) external; + + /** + * @notice Sets the maximum delegation ratio allowed for an allocation + * @param maximumDelegationRatio The maximum delegation ratio allowed for an allocation + */ + function setMaximumDelegationRatio(uint32 maximumDelegationRatio) external; + + /** + * @notice Sets the rewards destination for an indexer to receive indexing rewards + * @dev Emits a {RewardsDestinationSet} event + * @param rewardsDestination The address where indexing rewards should be sent + */ + function setRewardsDestination(address rewardsDestination) external; + + /** + * @notice Gets the details of an allocation + * For legacy allocations use {getLegacyAllocation} + * @param allocationId The id of the allocation + */ function getAllocation(address allocationId) external view returns (Allocation.State memory); + /** + * @notice Gets the details of a legacy allocation + * For non-legacy allocations use {getAllocation} + * @param allocationId The id of the allocation + */ function getLegacyAllocation(address allocationId) external view returns (LegacyAllocation.State memory); + /** + * @notice Encodes the allocation proof for EIP712 signing + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + */ function encodeAllocationProof(address indexer, address allocationId) external view returns (bytes32); } diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index 34c876135..0df8f6e21 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -1,25 +1,66 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +/** + * @title Allocation library + * @notice A library to handle Allocations. + */ library Allocation { using Allocation for State; + /** + * @notice Allocation details + */ struct State { + // Indexer that owns the allocation address indexer; + // Subgraph deployment id the allocation is for bytes32 subgraphDeploymentId; + // Number of tokens allocated uint256 tokens; + // Timestamp when the allocation was created uint256 createdAt; + // Timestamp when the allocation was closed uint256 closedAt; + // Timestamp when the last POI was presented uint256 lastPOIPresentedAt; + // Accumulated rewards per allocated token uint256 accRewardsPerAllocatedToken; + // Accumulated rewards per allocated token that are pending to be claimed + // due to an allocation resize uint256 accRewardsPending; } + /** + * @notice Thrown when attempting to create an allocation with an existing id + * @param allocationId The allocation id + */ error AllocationAlreadyExists(address allocationId); + + /** + * @notice Thrown when trying to perform an operation on a non-existent allocation + * @param allocationId The allocation id + */ error AllocationDoesNotExist(address allocationId); + + /** + * @notice Thrown when trying to perform an operation on a closed allocation + * @param allocationId The allocation id + * @param closedAt The timestamp when the allocation was closed + */ error AllocationClosed(address allocationId, uint256 closedAt); - error AllocationZeroTokens(address allocationId); + /** + * @notice Create a new allocation + * @dev Requirements: + * - The allocation must not exist + * @param self The allocation list mapping + * @param indexer The indexer that owns the allocation + * @param allocationId The allocation id + * @param subgraphDeploymentId The subgraph deployment id the allocation is for + * @param tokens The number of tokens allocated + * @param accRewardsPerAllocatedToken The initial accumulated rewards per allocated token + */ function create( mapping(address => State) storage self, address indexer, @@ -46,8 +87,14 @@ library Allocation { return allocation; } - // Update POI timestamp and take rewards snapshot - // For stale POIs this ensures the rewards are not collected with the next valid POI + /** + * @notice Present a POI for an allocation + * @dev It only updates the last POI presented timestamp. + * Requirements: + * - The allocation must be open + * @param self The allocation list mapping + * @param allocationId The allocation id + */ function presentPOI(mapping(address => State) storage self, address allocationId) internal returns (State memory) { State storage allocation = _get(self, allocationId); require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); @@ -56,6 +103,14 @@ library Allocation { return allocation; } + /** + * @notice Update the accumulated rewards per allocated token for an allocation + * @dev Requirements: + * - The allocation must be open + * @param self The allocation list mapping + * @param allocationId The allocation id + * @param accRewardsPerAllocatedToken The new accumulated rewards per allocated token + */ function snapshotRewards( mapping(address => State) storage self, address allocationId, @@ -68,6 +123,13 @@ library Allocation { return allocation; } + /** + * @notice Update the accumulated rewards pending to be claimed for an allocation + * @dev Requirements: + * - The allocation must be open + * @param self The allocation list mapping + * @param allocationId The allocation id + */ function clearPendingRewards( mapping(address => State) storage self, address allocationId @@ -79,6 +141,13 @@ library Allocation { return allocation; } + /** + * @notice Close an allocation + * @dev Requirements: + * - The allocation must be open + * @param self The allocation list mapping + * @param allocationId The allocation id + */ function close(mapping(address => State) storage self, address allocationId) internal returns (State memory) { State storage allocation = _get(self, allocationId); require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); @@ -87,22 +156,45 @@ library Allocation { return allocation; } + /** + * @notice Get an allocation + * @param self The allocation list mapping + * @param allocationId The allocation id + */ function get(mapping(address => State) storage self, address allocationId) internal view returns (State memory) { return _get(self, allocationId); } + /** + * @notice Checks if an allocation exists + * @param self The allocation + */ function exists(State memory self) internal pure returns (bool) { return self.createdAt != 0; } + /** + * @notice Checks if an allocation is open + * @param self The allocation + */ function isOpen(State memory self) internal pure returns (bool) { return self.exists() && self.closedAt == 0; } + /** + * @notice Checks if an allocation is closed + * @param self The allocation + */ function isAltruistic(State memory self) internal pure returns (bool) { return self.exists() && self.tokens == 0; } + /** + * @notice Get the allocation for an allocation id + * @dev Reverts if the allocation does not exist + * @param self The allocation list mapping + * @param allocationId The allocation id + */ function _get(mapping(address => State) storage self, address allocationId) private view returns (State storage) { State storage allocation = self[allocationId]; require(allocation.exists(), AllocationDoesNotExist(allocationId)); diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index b08802ec3..7926ca30a 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -1,15 +1,19 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +/** + * @title Attestation library + * @notice A library to handle Attestation. + */ library Attestation { - // Receipt content sent from the service provider in response to request + /// @notice Receipt content sent from the service provider in response to request struct Receipt { bytes32 requestCID; bytes32 responseCID; bytes32 subgraphDeploymentId; } - // Attestation sent from the service provider in response to a request + /// @notice Attestation sent from the service provider in response to a request struct State { bytes32 requestCID; bytes32 responseCID; @@ -19,7 +23,7 @@ library Attestation { uint8 v; } - // Attestation size is the sum of the receipt (96) + signature (65) + /// @notice Attestation size is the sum of the receipt (96) + signature (65) uint256 private constant ATTESTATION_SIZE_BYTES = RECEIPT_SIZE_BYTES + SIG_SIZE_BYTES; uint256 private constant RECEIPT_SIZE_BYTES = 96; diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol index 604a3bd78..81e6bcdcb 100644 --- a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -1,42 +1,93 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +/** + * @title LegacyAllocation library + * @notice A library to handle legacy Allocations. + */ library LegacyAllocation { using LegacyAllocation for State; + /** + * @notice Legacy allocation details + * @dev Note that we are only storing the indexer and subgraphDeploymentId. The main point of tracking legacy allocations + * is to prevent them from being re used on the Subgraph Service. We don't need to store the rest of the allocation details. + */ struct State { address indexer; - bytes32 subgraphDeploymentID; + bytes32 subgraphDeploymentId; } + /** + * @notice Thrown when attempting to migrate an allocation with an existing id + * @param allocationId The allocation id + */ error LegacyAllocationExists(address allocationId); + + /** + * @notice Thrown when trying to get a non-existent allocation + * @param allocationId The allocation id + */ error LegacyAllocationDoesNotExist(address allocationId); + + /** + * @notice Thrown when trying to migrate an allocation that has already been migrated + * @param allocationId The allocation id + */ error LegacyAllocationAlreadyMigrated(address allocationId); + /** + * @notice Migrate a legacy allocation + * @dev Requirements: + * - The allocation must not exist + * @param self The legacy allocation list mapping + * @param indexer The indexer that owns the allocation + * @param allocationId The allocation id + * @param subgraphDeploymentId The subgraph deployment id the allocation is for + */ function migrate( mapping(address => State) storage self, address indexer, address allocationId, - bytes32 subgraphDeploymentID + bytes32 subgraphDeploymentId ) internal { require(!self[allocationId].exists(), LegacyAllocationExists(allocationId)); - State memory allocation = State({ indexer: indexer, subgraphDeploymentID: subgraphDeploymentID }); + State memory allocation = State({ indexer: indexer, subgraphDeploymentId: subgraphDeploymentId }); self[allocationId] = allocation; } + /** + * @notice Get a legacy allocation + * @param self The legacy allocation list mapping + * @param allocationId The allocation id + */ function get(mapping(address => State) storage self, address allocationId) internal view returns (State memory) { return _get(self, allocationId); } + /** + * @notice Revert if a legacy allocation exists + * @param self The legacy allocation list mapping + * @param allocationId The allocation id + */ function revertIfExists(mapping(address => State) storage self, address allocationId) internal view { require(!self[allocationId].exists(), LegacyAllocationExists(allocationId)); } + /** + * @notice Check if a legacy allocation exists + * @param self The legacy allocation + */ function exists(State memory self) internal pure returns (bool) { return self.indexer != address(0); } + /** + * @notice Get a legacy allocation + * @param self The legacy allocation list mapping + * @param allocationId The allocation id + */ function _get(mapping(address => State) storage self, address allocationId) private view returns (State storage) { State storage allocation = self[allocationId]; require(allocation.exists(), LegacyAllocationDoesNotExist(allocationId)); diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 5a4a9c58f..ec5d869a1 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -14,6 +14,12 @@ import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; +/** + * @title AllocationManager contract + * @notice A helper contract implementing allocation lifecycle management. + * Allows opening, resizing, and closing allocations, as well as collecting indexing rewards by presenting a Proof + * of Indexing (POI). + */ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, AllocationManagerV1Storage { using ProvisionTracker for mapping(address => uint256); using Allocation for mapping(address => Allocation.State); @@ -21,14 +27,16 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca using LegacyAllocation for mapping(address => LegacyAllocation.State); using PPMMath for uint256; - // -- Immutables -- + ///@dev EIP712 typehash for allocation proof bytes32 private immutable EIP712_ALLOCATION_PROOF_TYPEHASH = keccak256("AllocationIdProof(address indexer,address allocationId)"); /** - * @dev Emitted when `indexer` allocated `tokens` amount to `subgraphDeploymentId` - * during `epoch`. - * `allocationId` indexer derived address used to identify the allocation. + * @notice Emitted when an indexer creates an allocation + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + * @param subgraphDeploymentId The id of the subgraph deployment + * @param tokens The amount of tokens allocated */ event AllocationCreated( address indexed indexer, @@ -37,6 +45,16 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca uint256 tokens ); + /** + * @notice Emitted when an indexer collects indexing rewards for an allocation + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + * @param subgraphDeploymentId The id of the subgraph deployment + * @param tokensRewards The amount of tokens collected + * @param tokensIndexerRewards The amount of tokens collected for the indexer + * @param tokensDelegationRewards The amount of tokens collected for delegators + * @param poi The POI presented + */ event IndexingRewardsCollected( address indexed indexer, address indexed allocationId, @@ -47,6 +65,14 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca bytes32 poi ); + /** + * @notice Emitted when an indexer resizes an allocation + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + * @param subgraphDeploymentId The id of the subgraph deployment + * @param newTokens The new amount of tokens allocated + * @param oldTokens The old amount of tokens allocated + */ event AllocationResized( address indexed indexer, address indexed allocationId, @@ -56,8 +82,11 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca ); /** - * @dev Emitted when `indexer` closes an allocation with id `allocationId`. - * An amount of `tokens` get unallocated from `subgraphDeploymentId`. + * @dev Emitted when an indexer closes an allocation + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + * @param subgraphDeploymentId The id of the subgraph deployment + * @param tokens The amount of tokens allocated */ event AllocationClosed( address indexed indexer, @@ -66,37 +95,99 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca uint256 tokens ); + /** + * @notice Emitted when a legacy allocation is migrated into the subgraph service + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + * @param subgraphDeploymentId The id of the subgraph deployment + */ event LegacyAllocationMigrated( address indexed indexer, address indexed allocationId, bytes32 indexed subgraphDeploymentId ); + /** + * @notice Emitted when an indexer sets a new indexing rewards destination + * @param indexer The address of the indexer + * @param rewardsDestination The address where indexing rewards should be sent + */ event RewardsDestinationSet(address indexed indexer, address indexed rewardsDestination); + /** + * @notice Thrown when an allocation proof is invalid + * Both `signer` and `allocationId` should match for a valid proof. + * @param signer The address that signed the proof + * @param allocationId The id of the allocation + */ error AllocationManagerInvalidAllocationProof(address signer, address allocationId); - error AllocationManagerInvalidAllocationId(); + + /** + * @notice Thrown when attempting to create an allocation with a zero allocation id + */ + error AllocationManagerInvalidZeroAllocationId(); + + /** + * @notice Thrown when attempting to create an allocation with zero tokens + * @param allocationId The id of the allocation + */ error AllocationManagerZeroTokensAllocation(address allocationId); + + /** + * @notice Thrown when attempting to collect indexing rewards on a closed allocationl + * @param allocationId The id of the allocation + */ error AllocationManagerAllocationClosed(address allocationId); + + /** + * @notice Thrown when attempting to resize an allocation with the same size + * @param allocationId The id of the allocation + * @param tokens The amount of tokens + */ error AllocationManagerAllocationSameSize(address allocationId, uint256 tokens); - error AllocationManagerInvalidZeroPOI(); + /** + * @notice Initializes the contract and parent contracts + */ function __AllocationManager_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init(name, version); __AllocationManager_init_unchained(name, version); } + /** + * @notice Initializes the contract + */ function __AllocationManager_init_unchained(string memory name, string memory version) internal onlyInitializing {} - function setRewardsDestination(address rewardsDestination) external { - _setRewardsDestination(msg.sender, rewardsDestination); - } - + /** + * @notice Imports a legacy allocation id into the subgraph service + * This is a governor only action that is required to prevent indexers from re-using allocation ids from the + * legacy staking contract. + * @param _indexer The address of the indexer + * @param _allocationId The id of the allocation + * @param _subgraphDeploymentId The id of the subgraph deployment + */ function _migrateLegacyAllocation(address _indexer, address _allocationId, bytes32 _subgraphDeploymentId) internal { legacyAllocations.migrate(_indexer, _allocationId, _subgraphDeploymentId); emit LegacyAllocationMigrated(_indexer, _allocationId, _subgraphDeploymentId); } + /** + * @notice Create an allocation + * @dev The `_allocationProof` is a 65-bytes Ethereum signed message of `keccak256(indexerAddress,allocationId)` + * + * Requirements: + * - `_allocationId` must not be the zero address + * + * Emits a {AllocationCreated} event + * + * @param _indexer The address of the indexer + * @param _allocationId The id of the allocation to be created + * @param _subgraphDeploymentId The subgraph deployment Id + * @param _tokens The amount of tokens to allocate + * @param _allocationProof Signed proof of allocation id address ownership + * @param _delegationRatio The delegation ratio to consider when locking tokens + */ function _allocate( address _indexer, address _allocationId, @@ -105,23 +196,23 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca bytes memory _allocationProof, uint32 _delegationRatio ) internal returns (Allocation.State memory) { - require(_allocationId != address(0), AllocationManagerInvalidAllocationId()); + require(_allocationId != address(0), AllocationManagerInvalidZeroAllocationId()); _verifyAllocationProof(_indexer, _allocationId, _allocationProof); // Ensure allocation id is not reused - // need to check both subgraph service (on create()) and legacy allocations + // need to check both subgraph service (on allocations.create()) and legacy allocations legacyAllocations.revertIfExists(_allocationId); Allocation.State memory allocation = allocations.create( _indexer, _allocationId, _subgraphDeploymentId, _tokens, - // allos can be resized now, so we need to always take snapshot _graphRewardsManager().onSubgraphAllocationUpdate(_subgraphDeploymentId) ); // Check that the indexer has enough tokens available + // Note that the delegation ratio ensures overdelegation cannot be used allocationProvisionTracker.lock(_graphStaking(), _indexer, _tokens, _delegationRatio); // Update total allocated tokens for the subgraph deployment @@ -133,17 +224,32 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca return allocation; } - // Update POI timestamp and take rewards snapshot even for 0 rewards - // This ensures the rewards are actually skipped and not collected with the next valid POI + /** + * @notice Present a POI to collect indexing rewards for an allocation + * This function will mint indexing rewards using the {RewardsManager} and distribute them to the indexer and delegators. + * + * To qualify for indexing rewards: + * - POI must be non-zero + * - POI must not be stale, i.e: older than `maxPOIStaleness` + * - allocation must not be altruistic (allocated tokens = 0) + * + * Note that indexers are required to periodically (at most every `maxPOIStaleness`) present POIs to collect rewards. + * Rewards will not be issued to stale POIs, which means that indexers are advised to present a zero POI if they are + * unable to present a valid one to prevent being locked out of future rewards. + * + * Emits a {IndexingRewardsCollected} event. + * + * @param _data Encoded data containing: + * - address `allocationId`: The id of the allocation to collect rewards for + * - bytes32 `poi`: The POI being presented + */ function _collectIndexingRewards(bytes memory _data) internal returns (uint256) { (address allocationId, bytes32 poi) = abi.decode(_data, (address, bytes32)); Allocation.State memory allocation = allocations.get(allocationId); + require(allocation.isOpen(), AllocationManagerAllocationClosed(allocationId)); - // Mint indexing rewards. To qualify: - // - POI must be non-zero - // - POI must not be stale, i.e: older than maxPOIStaleness - // - allocation must not be altruistic (tokens = 0) + // Mint indexing rewards if all conditions are met uint256 timeSinceLastPOI = block.number - Math.max(allocation.createdAt, allocation.lastPOIPresentedAt); uint256 tokensRewards = (timeSinceLastPOI <= maxPOIStaleness && poi != bytes32(0) && !allocation.isAltruistic()) ? _graphRewardsManager().takeRewards(allocationId) @@ -173,7 +279,6 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca } // Distribute rewards to delegators - // TODO: remove the uint8 cast when PRs are merged uint256 delegatorCut = _graphStaking().getDelegationFeeCut( allocation.indexer, address(this), @@ -208,6 +313,21 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca return tokensRewards; } + /** + * @notice Resize an allocation + * @dev Will lock or release tokens in the provision tracker depending on the new allocation size. + * Rewards accrued but not issued before the resize will be accounted for as pending rewards. + * These will be paid out when the indexer presents a POI. + * + * Requirements: + * - `_tokens` must be different from the current allocation size + * + * Emits a {AllocationResized} event. + * + * @param _allocationId The id of the allocation to be resized + * @param _tokens The new amount of tokens to allocate + * @param _delegationRatio The delegation ratio to consider when locking tokens + */ function _resizeAllocation( address _allocationId, uint256 _tokens, @@ -245,6 +365,17 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca return allocations[_allocationId]; } + /** + * @notice Close an allocation + * Does not require presenting a POI, use {_collectIndexingRewards} to present a POI and collect rewards + * @dev Note that allocations are nowlong lived. All service payments, including indexing rewards, should be collected periodically + * without the need of closing the allocation. Allocations should only be closed when indexers want to reclaim the allocated + * tokens for other purposes. + * + * Emits a {AllocationClosed} event + * + * @param _allocationId The id of the allocation to be closed + */ function _closeAllocation(address _allocationId) internal returns (Allocation.State memory) { Allocation.State memory allocation = allocations.get(_allocationId); @@ -266,28 +397,51 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca return allocations[_allocationId]; } + /** + * @notice Sets the rewards destination for an indexer to receive indexing rewards + * @dev Emits a {RewardsDestinationSet} event + * @param _rewardsDestination The address where indexing rewards should be sent + */ function _setRewardsDestination(address _indexer, address _rewardsDestination) internal { rewardsDestination[_indexer] = _rewardsDestination; emit RewardsDestinationSet(_indexer, _rewardsDestination); } + /** + * @notice Gets the details of an allocation + * @param _allocationId The id of the allocation + */ function _getAllocation(address _allocationId) internal view returns (Allocation.State memory) { return allocations.get(_allocationId); } + /** + * @notice Gets the details of a legacy allocation + * @param _allocationId The id of the legacy allocation + */ function _getLegacyAllocation(address _allocationId) internal view returns (LegacyAllocation.State memory) { return legacyAllocations.get(_allocationId); } - // -- Allocation Proof Verification -- - // Caller must prove that they own the private key for the allocationId address - // The proof is an EIP712 signed message of (indexer,allocationId) + /** + * @notice Verifies ownsership of an allocation id by verifying an EIP712 allocation proof + * @dev Requirements: + * - Signer must be the allocation id address + * @param _indexer The address of the indexer + * @param _allocationId The id of the allocation + * @param _proof The EIP712 proof, an EIP712 signed message of (indexer,allocationId) + */ function _verifyAllocationProof(address _indexer, address _allocationId, bytes memory _proof) internal view { bytes32 digest = _encodeAllocationProof(_indexer, _allocationId); address signer = ECDSA.recover(digest, _proof); require(signer == _allocationId, AllocationManagerInvalidAllocationProof(signer, _allocationId)); } + /** + * @notice Encodes the allocation proof for EIP712 signing + * @param _indexer The address of the indexer + * @param _allocationId The id of the allocation + */ function _encodeAllocationProof(address _indexer, address _allocationId) internal view returns (bytes32) { return _hashTypedDataV4(keccak256(abi.encode(EIP712_ALLOCATION_PROOF_TYPEHASH, _indexer, _allocationId))); } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol index 700c0243c..da812f5c1 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol @@ -5,14 +5,19 @@ import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; abstract contract AllocationManagerV1Storage { + /// @notice Allocation details mapping(address allocationId => Allocation.State allocation) public allocations; - mapping(address indexer => uint256 tokens) public allocationProvisionTracker; + + /// @notice Legacy allocation details mapping(address allocationId => LegacyAllocation.State allocation) public legacyAllocations; - /// @notice Maximum amount of since last POI was presented to qualify for indexing rewards + /// @notice Tracks allocated tokens per indexer + mapping(address indexer => uint256 tokens) public allocationProvisionTracker; + + /// @notice Maximum amount of time, in seconds, allowed between presenting POIs to qualify for indexing rewards uint256 public maxPOIStaleness; - /// @dev Destination of accrued rewards + /// @notice Destination of accrued indexing rewards mapping(address indexer => address destination) public rewardsDestination; /// @notice Track total tokens allocated per subgraph deployment diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index c6ed521b6..63ebcf9a1 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -7,20 +7,39 @@ import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { Attestation } from "../libraries/Attestation.sol"; +/** + * @title AttestationManager contract + * @notice A helper contract implementing attestation verification. + * Uses a custom implementation of EIP712 for backwards compatibility with attestations. + */ abstract contract AttestationManager is Initializable, AttestationManagerV1Storage { + /// @notice EIP712 type hash for Receipt struct bytes32 private constant RECEIPT_TYPE_HASH = keccak256("Receipt(bytes32 requestCID,bytes32 responseCID,bytes32 subgraphDeploymentID)"); + /// @notice EIP712 domain type hash bytes32 private constant DOMAIN_TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); + + /// @notice EIP712 domain name bytes32 private constant DOMAIN_NAME_HASH = keccak256("Graph Protocol"); + + /// @notice EIP712 domain version bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); + + /// @notice EIP712 domain salt bytes32 private constant DOMAIN_SALT = 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; + /** + * @dev Initialize the AttestationManager contract and parent contracts + */ function __AttestationManager_init() internal onlyInitializing { __AttestationManager_init_unchained(); } + /** + * @dev Initialize the AttestationManager contract + */ function __AttestationManager_init_unchained() internal onlyInitializing { _domainSeparator = keccak256( abi.encode( diff --git a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol index cfb925f5b..5bf57af65 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.26; abstract contract AttestationManagerV1Storage { + /// @dev EIP712 domain separator bytes32 internal _domainSeparator; /// @dev Gap to allow adding variables in future upgrades diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index 8bfaee861..920a0ae5e 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -6,20 +6,51 @@ import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; +/** + * @title Directory contract + * @notice This contract is meant to be inherited by {SubgraphService} contract. + * It contains the addresses of the contracts that the contract interacts with. + * Uses immutable variables to minimize gas costs. + */ abstract contract Directory { + /// @notice The Subgraph Service contract address ISubgraphService private immutable SUBGRAPH_SERVICE; + + /// @notice The Dispute Manager contract address IDisputeManager private immutable DISPUTE_MANAGER; + + /// @notice The TAP Collector contract address + /// @dev Required to collect payments via Graph Horizon payments protocol ITAPCollector private immutable TAP_COLLECTOR; + + /// @notice The Curation contract address + /// @dev Required for curation fees distribution ICuration private immutable CURATION; + /** + * @notice Emitted when the Directory is initialized + * @param subgraphService The Subgraph Service contract address + * @param disputeManager The Dispute Manager contract address + * @param tapCollector The TAP Collector contract address + * @param curation The Curation contract address + */ event SubgraphServiceDirectoryInitialized( address subgraphService, address disputeManager, address tapCollector, address curation ); + + /** + * @notice Thrown when the caller is not the Dispute Manager + * @param caller The caller address + * @param disputeManager The Dispute Manager address + */ error DirectoryNotDisputeManager(address caller, address disputeManager); + /** + * @notice Checks that the caller is the Dispute Manager + */ modifier onlyDisputeManager() { require( msg.sender == address(DISPUTE_MANAGER), @@ -28,6 +59,13 @@ abstract contract Directory { _; } + /** + * @notice Constructor for the Directory contract + * @param subgraphService The Subgraph Service contract address + * @param disputeManager The Dispute Manager contract address + * @param tapCollector The TAP Collector contract address + * @param curation The Curation contract address + */ constructor(address subgraphService, address disputeManager, address tapCollector, address curation) { SUBGRAPH_SERVICE = ISubgraphService(subgraphService); DISPUTE_MANAGER = IDisputeManager(disputeManager); @@ -37,18 +75,30 @@ abstract contract Directory { emit SubgraphServiceDirectoryInitialized(subgraphService, disputeManager, tapCollector, curation); } + /** + * @notice Returns the Subgraph Service contract address + */ function _subgraphService() internal view returns (ISubgraphService) { return SUBGRAPH_SERVICE; } + /** + * @notice Returns the Dispute Manager contract address + */ function _disputeManager() internal view returns (IDisputeManager) { return DISPUTE_MANAGER; } + /** + * @notice Returns the TAP Collector contract address + */ function _tapCollector() internal view returns (ITAPCollector) { return TAP_COLLECTOR; } + /** + * @notice Returns the Curation contract address + */ function _curation() internal view returns (ICuration) { return CURATION; } From d369c0844c9aa27f3e855fc4467ff1edc7a06d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 3 Jun 2024 15:35:22 -0300 Subject: [PATCH 096/277] chore: lint fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 2 + .../utilities/ProvisionManager.sol | 94 ++++++++++--------- .../contracts/interfaces/ITAPCollector.sol | 1 - .../internal/IHorizonStakingMain.sol | 1 - .../contracts/payments/PaymentsEscrow.sol | 13 +-- .../contracts/staking/HorizonStaking.sol | 6 +- .../contracts/SubgraphService.sol | 10 +- .../contracts/interfaces/IDisputeManager.sol | 9 +- .../contracts/utilities/AllocationManager.sol | 13 ++- .../utilities/AttestationManager.sol | 4 +- 10 files changed, 81 insertions(+), 72 deletions(-) diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index d9f2ec1e5..f986224b3 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -29,6 +29,7 @@ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1 /** * @notice Initializes the contract and any parent contracts. */ + // solhint-disable-next-line func-name-mixedcase function __DataService_init() internal onlyInitializing { __DataService_init_unchained(); } @@ -36,6 +37,7 @@ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1 /** * @notice Initializes the contract. */ + // solhint-disable-next-line func-name-mixedcase function __DataService_init_unchained() internal onlyInitializing { __ProvisionManager_init_unchained(); } diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 520b7a24b..24230997e 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -135,6 +135,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa /** * @notice Initializes the contract and any parent contracts. */ + // solhint-disable-next-line func-name-mixedcase function __ProvisionManager_init() internal onlyInitializing { __ProvisionManager_init_unchained(); } @@ -143,6 +144,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * @notice Initializes the contract. * @dev All parameters set to their entire range as valid. */ + // solhint-disable-next-line func-name-mixedcase function __ProvisionManager_init_unchained() internal onlyInitializing { _setProvisionTokensRange(type(uint256).min, type(uint256).max); _setDelegationRatioRange(type(uint32).min, type(uint32).max); @@ -164,6 +166,52 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa _graphStaking().acceptProvisionParameters(_serviceProvider); } + // -- setters -- + + /** + * @notice Sets the range for the provision tokens. + * @param _min The minimum allowed value for the provision tokens. + * @param _max The maximum allowed value for the provision tokens. + */ + function _setProvisionTokensRange(uint256 _min, uint256 _max) internal { + minimumProvisionTokens = _min; + maximumProvisionTokens = _max; + emit ProvisionTokensRangeSet(_min, _max); + } + + /** + * @notice Sets the range for the delegation ratio. + * @param _min The minimum allowed value for the delegation ratio. + * @param _max The maximum allowed value for the delegation ratio. + */ + function _setDelegationRatioRange(uint32 _min, uint32 _max) internal { + minimumDelegationRatio = _min; + maximumDelegationRatio = _max; + emit DelegationRatioRangeSet(_min, _max); + } + + /** + * @notice Sets the range for the verifier cut. + * @param _min The minimum allowed value for the max verifier cut. + * @param _max The maximum allowed value for the max verifier cut. + */ + function _setVerifierCutRange(uint32 _min, uint32 _max) internal { + minimumVerifierCut = _min; + maximumVerifierCut = _max; + emit VerifierCutRangeSet(_min, _max); + } + + /** + * @notice Sets the range for the thawing period. + * @param _min The minimum allowed value for the thawing period. + * @param _max The maximum allowed value for the thawing period. + */ + function _setThawingPeriodRange(uint64 _min, uint64 _max) internal { + minimumThawingPeriod = _min; + maximumThawingPeriod = _max; + emit ThawingPeriodRangeSet(_min, _max); + } + // -- checks -- /** @@ -241,52 +289,6 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa } } - // -- setters -- - - /** - * @notice Sets the range for the provision tokens. - * @param _min The minimum allowed value for the provision tokens. - * @param _max The maximum allowed value for the provision tokens. - */ - function _setProvisionTokensRange(uint256 _min, uint256 _max) internal { - minimumProvisionTokens = _min; - maximumProvisionTokens = _max; - emit ProvisionTokensRangeSet(_min, _max); - } - - /** - * @notice Sets the range for the delegation ratio. - * @param _min The minimum allowed value for the delegation ratio. - * @param _max The maximum allowed value for the delegation ratio. - */ - function _setDelegationRatioRange(uint32 _min, uint32 _max) internal { - minimumDelegationRatio = _min; - maximumDelegationRatio = _max; - emit DelegationRatioRangeSet(_min, _max); - } - - /** - * @notice Sets the range for the verifier cut. - * @param _min The minimum allowed value for the max verifier cut. - * @param _max The maximum allowed value for the max verifier cut. - */ - function _setVerifierCutRange(uint32 _min, uint32 _max) internal { - minimumVerifierCut = _min; - maximumVerifierCut = _max; - emit VerifierCutRangeSet(_min, _max); - } - - /** - * @notice Sets the range for the thawing period. - * @param _min The minimum allowed value for the thawing period. - * @param _max The maximum allowed value for the thawing period. - */ - function _setThawingPeriodRange(uint64 _min, uint64 _max) internal { - minimumThawingPeriod = _min; - maximumThawingPeriod = _max; - emit ThawingPeriodRangeSet(_min, _max); - } - // -- getters -- /** diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 2e5a47c05..28561e2ce 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; -import { IGraphPayments } from "./IGraphPayments.sol"; import { IPaymentsCollector } from "./IPaymentsCollector.sol"; /** diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 201e1b75a..0118479a1 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.26; -import { IHorizonStakingBase } from "./IHorizonStakingBase.sol"; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; /** diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index a03ac7409..8b9e8c768 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -218,12 +218,13 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { /** * @notice See {IPaymentsEscrow-deposit} - * @param receiver The address of the receiver - * @param tokens The amount of tokens to deposit + * @param _payer The address of the payer + * @param _receiver The address of the receiver + * @param _tokens The amount of tokens to deposit */ - function _deposit(address payer, address receiver, uint256 tokens) internal { - escrowAccounts[payer][receiver].balance += tokens; - _graphToken().pullTokens(msg.sender, tokens); - emit Deposit(payer, receiver, tokens); + function _deposit(address _payer, address _receiver, uint256 _tokens) internal { + escrowAccounts[_payer][_receiver].balance += _tokens; + _graphToken().pullTokens(msg.sender, _tokens); + emit Deposit(_payer, _receiver, _tokens); } } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index d0a404040..3ffc3e4b6 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -560,15 +560,15 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice See {IHorizonStakingMain-withdraw}. * @param _serviceProvider Address of service provider to withdraw funds from - * @param revertIfThawing If true, the function will revert if the tokens are still thawing + * @param _revertIfThawing If true, the function will revert if the tokens are still thawing */ - function _withdraw(address _serviceProvider, bool revertIfThawing) private { + function _withdraw(address _serviceProvider, bool _revertIfThawing) private { // Get tokens available for withdraw and update balance ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; require(tokensToWithdraw != 0, HorizonStakingInvalidZeroTokens()); - if (revertIfThawing) { + if (_revertIfThawing) { require( block.timestamp >= sp.__DEPRECATED_tokensLockedUntil, HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index f6fa952e5..fb113c24c 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -231,11 +231,11 @@ contract SubgraphService is * Reverts if the payment type is not supported. * @dev This function is the equivalent of the `collect` function for query fees and the `closeAllocation` function * for indexing rewards in the legacy Staking contract. - * + * * Requirements: * - The indexer must be registered * - The provision must be valid according to the subgraph service rules - * + * * Emits a {ServicePaymentCollected} event. Emits payment type specific events. * * For query fees, see {SubgraphService-_collectQueryFees} for more details. @@ -349,11 +349,11 @@ contract SubgraphService is /** * @notice Get allocation data to calculate rewards issuance * @dev Implements {IRewardsIssuer.getAllocationData} - * @dev Note that this is slightly different than {getAllocation}. It returns an + * @dev Note that this is slightly different than {getAllocation}. It returns an * unstructured subset of the allocation data, which is the minimum required to mint rewards. - * + * * Should only be used by the {RewardsManager}. - * + * * @param allocationId The allocation Id * @return indexer The indexer address * @return subgraphDeploymentId Subgraph deployment id for the allocation diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 0da818cfa..f53b0f538 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -5,7 +5,6 @@ pragma solidity 0.8.26; import { Attestation } from "../libraries/Attestation.sol"; interface IDisputeManager { - /// @notice Types of disputes that can be created enum DisputeType { Null, @@ -58,7 +57,7 @@ interface IDisputeManager { * @param minimumDeposit The minimum deposit required to create a dispute. */ event MinimumDepositSet(uint256 minimumDeposit); - + /** * @notice Emitted when max slashing cut is set. * @param maxSlashingCut The maximum slashing cut that can be set. @@ -70,7 +69,7 @@ interface IDisputeManager { * @param fishermanRewardCut The fisherman reward cut. */ event FishermanRewardCutSet(uint32 fishermanRewardCut); - + /** * @notice Emitted when subgraph service is set. * @param subgraphService The address of the subgraph service. @@ -204,6 +203,8 @@ interface IDisputeManager { function cancelDispute(bytes32 disputeId) external; + function setSubgraphService(address subgraphService) external; + // -- Getters -- function getVerifierCut() external view returns (uint32); @@ -220,6 +221,4 @@ interface IDisputeManager { Attestation.State memory attestation1, Attestation.State memory attestation2 ) external pure returns (bool); - - function setSubgraphService(address subgraphService) external; } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index ec5d869a1..7b8ba6c50 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -149,15 +149,20 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca /** * @notice Initializes the contract and parent contracts */ - function __AllocationManager_init(string memory name, string memory version) internal onlyInitializing { - __EIP712_init(name, version); - __AllocationManager_init_unchained(name, version); + // solhint-disable-next-line func-name-mixedcase + function __AllocationManager_init(string memory _name, string memory _version) internal onlyInitializing { + __EIP712_init(_name, _version); + __AllocationManager_init_unchained(_name, _version); } /** * @notice Initializes the contract */ - function __AllocationManager_init_unchained(string memory name, string memory version) internal onlyInitializing {} + // solhint-disable-next-line func-name-mixedcase + function __AllocationManager_init_unchained( + string memory _name, + string memory _version + ) internal onlyInitializing {} /** * @notice Imports a legacy allocation id into the subgraph service diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index 63ebcf9a1..0d8405917 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -20,7 +20,7 @@ abstract contract AttestationManager is Initializable, AttestationManagerV1Stora /// @notice EIP712 domain type hash bytes32 private constant DOMAIN_TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); - + /// @notice EIP712 domain name bytes32 private constant DOMAIN_NAME_HASH = keccak256("Graph Protocol"); @@ -33,6 +33,7 @@ abstract contract AttestationManager is Initializable, AttestationManagerV1Stora /** * @dev Initialize the AttestationManager contract and parent contracts */ + // solhint-disable-next-line func-name-mixedcase function __AttestationManager_init() internal onlyInitializing { __AttestationManager_init_unchained(); } @@ -40,6 +41,7 @@ abstract contract AttestationManager is Initializable, AttestationManagerV1Stora /** * @dev Initialize the AttestationManager contract */ + // solhint-disable-next-line func-name-mixedcase function __AttestationManager_init_unchained() internal onlyInitializing { _domainSeparator = keccak256( abi.encode( From 9ed2a722fa03058b57bcbb922e6f11bb6393eee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 3 Jun 2024 16:14:15 -0300 Subject: [PATCH 097/277] chore: trim unused code from LibFixedMath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/libraries/LibFixedMath.sol | 150 ------------------ 1 file changed, 150 deletions(-) diff --git a/packages/horizon/contracts/libraries/LibFixedMath.sol b/packages/horizon/contracts/libraries/LibFixedMath.sol index fd29b5e53..1a941ed11 100644 --- a/packages/horizon/contracts/libraries/LibFixedMath.sol +++ b/packages/horizon/contracts/libraries/LibFixedMath.sol @@ -27,13 +27,6 @@ library LibFixedMath { int256 private constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000); // 2**255 int256 private constant MIN_FIXED_VAL = type(int256).min; - // 1^2 (in fixed-point) - int256 private constant FIXED_1_SQUARED = - int256(0x4000000000000000000000000000000000000000000000000000000000000000); - // 1 - int256 private constant LN_MAX_VAL = FIXED_1; - // e ^ -63.875 - int256 private constant LN_MIN_VAL = int256(0x0000000000000000000000000000000000000000000000000000000733048c5a); // 0 int256 private constant EXP_MAX_VAL = 0; // -63.875 @@ -44,11 +37,6 @@ library LibFixedMath { f = FIXED_1; } - /// @dev Returns the addition of two fixed point numbers, reverting on overflow. - 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. function sub(int256 a, int256 b) internal pure returns (int256 c) { if (b == MIN_FIXED_VAL) { @@ -62,11 +50,6 @@ library LibFixedMath { c = _mul(a, b) / FIXED_1; } - /// @dev Returns the division of two fixed point numbers. - 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. function mulDiv(int256 a, int256 n, int256 d) internal pure returns (int256 c) { c = _div(_mul(a, n), d); @@ -86,149 +69,16 @@ library LibFixedMath { return uint256(uint256(c) >> 127); } - /// @dev Returns the absolute value of a fixed point number. - function abs(int256 f) internal pure returns (int256 c) { - if (f == MIN_FIXED_VAL) { - revert("out-of-bounds"); - } - if (f >= 0) { - c = f; - } else { - c = -f; - } - } - - /// @dev Returns 1 / `x`, where `x` is a fixed-point number. - 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. - function toFixed(int256 n) internal pure returns (int256 f) { - f = _mul(n, FIXED_1); - } - /// @dev Convert signed `n` / `d` to a fixed-point number. 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. - /// Reverts if `n` is too large to fit in a fixed-point number. - function toFixed(uint256 n) internal pure returns (int256 f) { - if (int256(n) < int256(0)) { - revert("out-of-bounds"); - } - f = _mul(int256(n), FIXED_1); - } - - /// @dev Convert unsigned `n` / `d` to a fixed-point number. - /// Reverts if `n` / `d` is too large to fit in a fixed-point number. - function toFixed(uint256 n, uint256 d) internal pure returns (int256 f) { - if (int256(n) < int256(0)) { - revert("out-of-bounds"); - } - if (int256(d) < int256(0)) { - revert("out-of-bounds"); - } - f = _div(_mul(int256(n), FIXED_1), int256(d)); - } - /// @dev Convert a fixed-point number to an integer. 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 - function ln(int256 x) internal pure returns (int256 r) { - if (x > LN_MAX_VAL) { - revert("out-of-bounds"); - } - if (x <= 0) { - revert("too-small"); - } - if (x == FIXED_1) { - return 0; - } - if (x <= LN_MIN_VAL) { - return EXP_MIN_VAL; - } - - int256 y; - int256 z; - int256 w; - unchecked { - // Rewrite the input as a quotient of negative natural exponents and a single residual q, such that 1 < q < 2 - // For example: log(0.3) = log(e^-1 * e^-0.25 * 1.0471028872385522) - // = 1 - 0.25 - log(1 + 0.0471028872385522) - // e ^ -32 - if (x <= int256(0x00000000000000000000000000000000000000000001c8464f76164760000000)) { - r -= int256(0x0000000000000000000000000000001000000000000000000000000000000000); // - 32 - x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000000001c8464f76164760000000); // / e ^ -32 - } - // e ^ -16 - if (x <= int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000)) { - r -= int256(0x0000000000000000000000000000000800000000000000000000000000000000); // - 16 - x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000); // / e ^ -16 - } - // e ^ -8 - if (x <= int256(0x00000000000000000000000000000000000afe10820813d78000000000000000)) { - r -= int256(0x0000000000000000000000000000000400000000000000000000000000000000); // - 8 - x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000afe10820813d78000000000000000); // / e ^ -8 - } - // e ^ -4 - if (x <= int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000)) { - r -= int256(0x0000000000000000000000000000000200000000000000000000000000000000); // - 4 - x = (x * FIXED_1) / int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000); // / e ^ -4 - } - // e ^ -2 - if (x <= int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000)) { - r -= int256(0x0000000000000000000000000000000100000000000000000000000000000000); // - 2 - x = (x * FIXED_1) / int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000); // / e ^ -2 - } - // e ^ -1 - if (x <= int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000)) { - r -= int256(0x0000000000000000000000000000000080000000000000000000000000000000); // - 1 - x = (x * FIXED_1) / int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000); // / e ^ -1 - } - // e ^ -0.5 - if (x <= int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000)) { - r -= int256(0x0000000000000000000000000000000040000000000000000000000000000000); // - 0.5 - x = (x * FIXED_1) / int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000); // / e ^ -0.5 - } - // e ^ -0.25 - if (x <= int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000)) { - r -= int256(0x0000000000000000000000000000000020000000000000000000000000000000); // - 0.25 - x = (x * FIXED_1) / int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000); // / e ^ -0.25 - } - // e ^ -0.125 - if (x <= int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) { - r -= int256(0x0000000000000000000000000000000010000000000000000000000000000000); // - 0.125 - x = (x * FIXED_1) / int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d); // / e ^ -0.125 - } - // `x` is now our residual in the range of 1 <= x <= 2 (or close enough). - - // Add the taylor series for log(1 + z), where z = x - 1 - z = y = x - FIXED_1; - w = (y * y) / FIXED_1; - r += (z * (0x100000000000000000000000000000000 - y)) / 0x100000000000000000000000000000000; - z = (z * w) / FIXED_1; // add y^01 / 01 - y^02 / 02 - r += (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / 0x200000000000000000000000000000000; - z = (z * w) / FIXED_1; // add y^03 / 03 - y^04 / 04 - r += (z * (0x099999999999999999999999999999999 - y)) / 0x300000000000000000000000000000000; - z = (z * w) / FIXED_1; // add y^05 / 05 - y^06 / 06 - r += (z * (0x092492492492492492492492492492492 - y)) / 0x400000000000000000000000000000000; - z = (z * w) / FIXED_1; // add y^07 / 07 - y^08 / 08 - r += (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / 0x500000000000000000000000000000000; - z = (z * w) / FIXED_1; // add y^09 / 09 - y^10 / 10 - r += (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / 0x600000000000000000000000000000000; - z = (z * w) / FIXED_1; // add y^11 / 11 - y^12 / 12 - r += (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / 0x700000000000000000000000000000000; - z = (z * w) / FIXED_1; // add y^13 / 13 - y^14 / 14 - 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 function exp(int256 x) internal pure returns (int256 r) { if (x < EXP_MIN_VAL) { From 4f6436ae1aed6eaadf4cce7838862e7dc57c0b62 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Mon, 3 Jun 2024 17:09:25 -0300 Subject: [PATCH 098/277] chore: add governance tests --- .../internal/IHorizonStakingBase.sol | 12 +++ .../internal/IHorizonStakingExtension.sol | 6 ++ .../contracts/staking/HorizonStakingBase.sol | 14 ++++ .../staking/HorizonStakingExtension.sol | 9 +++ .../test/staking/governance/governance.t.sol | 77 +++++++++++++++++++ 5 files changed, 118 insertions(+) create mode 100644 packages/horizon/test/staking/governance/governance.t.sol diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index 808c738f1..522ddf44e 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -167,4 +167,16 @@ interface IHorizonStakingBase { * @notice Gets the maximum allowed thawing period for a provision. */ function getMaxThawingPeriod() external view returns (uint64); + + /** + * @notice Return true if the verifier is an allowed locked verifier. + * @param verifier Address of the verifier + * @return True if verifier is allowed locked verifier, false otherwise + */ + function isAllowedLockedVerifier(address verifier) external view returns (bool); + + /** + * @notice Return true if delegation slashing is enabled, false otherwise. + */ + function isDelegationSlashingEnabled() external view returns (bool); } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 825ce2292..a51b1871d 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -164,4 +164,10 @@ interface IHorizonStakingExtension { * @return Total tokens allocated to subgraph */ function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view returns (uint256); + + /** + * @notice Retrun the time in blocks to unstake + * @return Thawing period in blocks + */ + function __DEPRECATED_getThawingPeriod() external view returns (uint64); } diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index c3eca6b43..eeac9f800 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -223,6 +223,20 @@ abstract contract HorizonStakingBase is return _maxThawingPeriod; } + /** + * @notice see {IHorizonStakingBase-isAllowedLockedVerifier}. + */ + function isAllowedLockedVerifier(address verifier) external view returns (bool) { + return _allowedLockedVerifiers[verifier]; + } + + /** + * @notice See {IHorizonStakingBase-isDelegationSlashingEnabled}. + */ + function isDelegationSlashingEnabled() external view returns (bool) { + return _delegationSlashingEnabled; + } + /** * @notice Deposit tokens into the service provider stake. * @dev TODO: After transition period move to IHorizonStakingMain. Temporarily it diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index c2d7685b4..7683523a7 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -297,6 +297,15 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki return _legacyOperatorAuth[serviceProvider][operator]; } + /** + * @notice Retrun the time in blocks to unstake + * Deprecated, now enforced by each data service (verifier) + * @return Thawing period in blocks + */ + function __DEPRECATED_getThawingPeriod() external view returns (uint64) { + return __DEPRECATED_thawingPeriod; + } + /** * @dev Receive an Indexer's stake from L1. * The specified amount is added to the indexer's stake; the indexer's diff --git a/packages/horizon/test/staking/governance/governance.t.sol b/packages/horizon/test/staking/governance/governance.t.sol new file mode 100644 index 000000000..988863f39 --- /dev/null +++ b/packages/horizon/test/staking/governance/governance.t.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingGovernanceTest is HorizonStakingTest { + + modifier useGovernor { + vm.startPrank(users.governor); + _; + } + + function testGovernance_SetAllowedLockedVerifier() public useGovernor { + staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); + assertTrue(staking.isAllowedLockedVerifier(subgraphDataServiceAddress)); + + // Use allowed verifier to set an operator with locked tokens + vm.startPrank(users.indexer); + staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + + assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + } + + function testGovernance_RevertWhen_VerifierNotAllowed() public useGovernor { + staking.setAllowedLockedVerifier(subgraphDataServiceAddress, false); + assertFalse(staking.isAllowedLockedVerifier(subgraphDataServiceAddress)); + + vm.startPrank(users.indexer); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingVerifierNotAllowed(address)", subgraphDataServiceAddress); + vm.expectRevert(expectedError); + staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + } + + function testGovernance_RevertWhen_SetAllowedLockedVerifier_NotGovernor() public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("ManagedOnlyGovernor()"); + vm.expectRevert(expectedError); + staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); + } + + function testGovernance_SetDelgationSlashing(bool enabled) public useGovernor { + staking.setDelegationSlashingEnabled(enabled); + assertEq(staking.isDelegationSlashingEnabled(), enabled); + } + + function testGovernance_SetDelgationSlashing_NotGovernor(bool enabled) public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("ManagedOnlyGovernor()"); + vm.expectRevert(expectedError); + staking.setDelegationSlashingEnabled(enabled); + } + + function testGovernance_ClearThawingPeriod(uint32 thawingPeriod) public useGovernor { + vm.store(address(staking), bytes32(uint256(13)), bytes32(uint256(thawingPeriod))); + assertEq(staking.__DEPRECATED_getThawingPeriod(), thawingPeriod); + + staking.clearThawingPeriod(); + assertEq(staking.__DEPRECATED_getThawingPeriod(), 0); + } + + function testGovernance_ClearThawingPeriod_NotGovernor() public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("ManagedOnlyGovernor()"); + vm.expectRevert(expectedError); + staking.clearThawingPeriod(); + } + + function testGovernance__SetMaxThawingPeriod(uint64 maxThawingPeriod) public useGovernor { + staking.setMaxThawingPeriod(maxThawingPeriod); + assertEq(staking.getMaxThawingPeriod(), maxThawingPeriod); + } + + function testGovernance__SetMaxThawingPeriod_NotGovernor() public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("ManagedOnlyGovernor()"); + vm.expectRevert(expectedError); + staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); + } +} \ No newline at end of file From 95bb9404155688dbe9af0b40cbc38c9bfc13e60f Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 10:48:17 -0300 Subject: [PATCH 099/277] chore: add tokens locked tests --- packages/horizon/test/GraphBase.t.sol | 3 +- .../horizon/test/staking/HorizonStaking.t.sol | 9 +++ .../test/staking/delegation/undelegate.t.sol | 16 +--- .../test/staking/governance/governance.t.sol | 16 ---- .../test/staking/operator/locked.t.sol | 26 +++++++ .../test/staking/operator/operator.t.sol | 15 +++- .../test/staking/provision/locked.t.sol | 78 +++++++++++++++++++ .../horizon/test/staking/slash/slash.t.sol | 8 +- packages/horizon/test/utils/Utils.sol | 12 +++ 9 files changed, 147 insertions(+), 36 deletions(-) create mode 100644 packages/horizon/test/staking/operator/locked.t.sol create mode 100644 packages/horizon/test/staking/provision/locked.t.sol create mode 100644 packages/horizon/test/utils/Utils.sol diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 699880050..cc4924842 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -15,8 +15,9 @@ import { HorizonStakingExtension } from "contracts/staking/HorizonStakingExtensi import { MockGRTToken } from "../contracts/mocks/MockGRTToken.sol"; import { Constants } from "./utils/Constants.sol"; import { Users } from "./utils/Users.sol"; +import { Utils } from "./utils/Utils.sol"; -abstract contract GraphBaseTest is Test, Constants { +abstract contract GraphBaseTest is Utils, Constants { /* Contracts */ diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index cc601ea90..cd2e9ba76 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -54,6 +54,15 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { _; } + modifier useLockedVerifier() { + address msgSender; + (, msgSender,) = vm.readCallers(); + resetPrank(users.governor); + staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); + resetPrank(msgSender); + _; + } + function _stakeTo(address to, uint256 amount) internal { approve(address(staking), amount); staking.stakeTo(to, amount); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 5eca15326..99683c825 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -13,9 +13,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - // TODO: maybe create a changePrank - vm.stopPrank(); - vm.startPrank(users.delegator); + resetPrank(users.delegator); Delegation memory delegation = _getDelegation(); _undelegate(delegation.shares); @@ -29,9 +27,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - // TODO: maybe create a changePrank - vm.stopPrank(); - vm.startPrank(users.delegator); + resetPrank(users.delegator); bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroShares()"); vm.expectRevert(expectedError); _undelegate(0); @@ -42,9 +38,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 delegationAmount, uint256 overDelegationShares ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - // TODO: maybe create a changePrank - vm.stopPrank(); - vm.startPrank(users.delegator); + resetPrank(users.delegator); Delegation memory delegation = _getDelegation(); vm.assume(overDelegationShares > delegation.shares); @@ -66,9 +60,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { useProvision(10_000_000 ether, 0, 0) useDelegation(delegationAmount) { - // TODO: maybe create a changePrank - vm.stopPrank(); - vm.startPrank(users.delegator); + resetPrank(users.delegator); uint256 minShares = delegationAmount - MIN_DELEGATION + 1; withdrawShares = bound(withdrawShares, minShares, delegationAmount - 1); bytes memory expectedError = abi.encodeWithSignature( diff --git a/packages/horizon/test/staking/governance/governance.t.sol b/packages/horizon/test/staking/governance/governance.t.sol index 988863f39..078d39ba2 100644 --- a/packages/horizon/test/staking/governance/governance.t.sol +++ b/packages/horizon/test/staking/governance/governance.t.sol @@ -15,22 +15,6 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { function testGovernance_SetAllowedLockedVerifier() public useGovernor { staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); assertTrue(staking.isAllowedLockedVerifier(subgraphDataServiceAddress)); - - // Use allowed verifier to set an operator with locked tokens - vm.startPrank(users.indexer); - staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); - - assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); - } - - function testGovernance_RevertWhen_VerifierNotAllowed() public useGovernor { - staking.setAllowedLockedVerifier(subgraphDataServiceAddress, false); - assertFalse(staking.isAllowedLockedVerifier(subgraphDataServiceAddress)); - - vm.startPrank(users.indexer); - bytes memory expectedError = abi.encodeWithSignature("HorizonStakingVerifierNotAllowed(address)", subgraphDataServiceAddress); - vm.expectRevert(expectedError); - staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); } function testGovernance_RevertWhen_SetAllowedLockedVerifier_NotGovernor() public useIndexer { diff --git a/packages/horizon/test/staking/operator/locked.t.sol b/packages/horizon/test/staking/operator/locked.t.sol new file mode 100644 index 000000000..b29d8890f --- /dev/null +++ b/packages/horizon/test/staking/operator/locked.t.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingOperatorLockedTest is HorizonStakingTest { + + function testOperatorLocked_Set() public useIndexer useLockedVerifier { + staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + } + + function testOperatorLocked_RevertWhen_VerifierNotAllowed() public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingVerifierNotAllowed(address)", subgraphDataServiceAddress); + vm.expectRevert(expectedError); + staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + } + + function testOperatorLocked_RevertWhen_CallerIsServiceProvider() public useIndexer useLockedVerifier { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCallerIsServiceProvider()"); + vm.expectRevert(expectedError); + staking.setOperatorLocked(users.indexer, subgraphDataServiceAddress, true); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/operator/operator.t.sol b/packages/horizon/test/staking/operator/operator.t.sol index f9f6e1692..034acdf8e 100644 --- a/packages/horizon/test/staking/operator/operator.t.sol +++ b/packages/horizon/test/staking/operator/operator.t.sol @@ -7,8 +7,21 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingOperatorTest is HorizonStakingTest { - function testOperator_SetOperator() public useIndexer { + function testOperator_SetOperator() public useOperator { + assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + } + + function testOperator_RevertWhen_CallerIsServiceProvider() public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCallerIsServiceProvider()"); + vm.expectRevert(expectedError); + staking.setOperator(users.indexer, subgraphDataServiceAddress, true); + } + + function testOperator_RemoveOperator() public useIndexer { staking.setOperator(users.operator, subgraphDataServiceAddress, true); assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + + staking.setOperator(users.operator, subgraphDataServiceAddress, false); + assertFalse(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/locked.t.sol b/packages/horizon/test/staking/provision/locked.t.sol new file mode 100644 index 000000000..3560dad39 --- /dev/null +++ b/packages/horizon/test/staking/provision/locked.t.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingProvisionLockedTest is HorizonStakingTest { + + function testProvisionLocked_Create( + uint256 amount + ) public useIndexer useStake(amount) useLockedVerifier { + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, 0); + + staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + + vm.startPrank(users.operator); + staking.provisionLocked( + users.indexer, + subgraphDataServiceAddress, + amount, + MAX_MAX_VERIFIER_CUT, + MAX_THAWING_PERIOD + ); + + provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, amount); + } + + function testProvisionLocked_RevertWhen_VerifierNotAllowed( + uint256 amount + ) public useIndexer useStake(amount) useLockedVerifier { + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, 0); + + // Set operator + staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + + // Disable locked verifier + vm.startPrank(users.governor); + staking.setAllowedLockedVerifier(subgraphDataServiceAddress, false); + + vm.startPrank(users.operator); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingVerifierNotAllowed(address)", subgraphDataServiceAddress); + vm.expectRevert(expectedError); + staking.provisionLocked( + users.indexer, + subgraphDataServiceAddress, + amount, + MAX_MAX_VERIFIER_CUT, + MAX_THAWING_PERIOD + ); + } + + function testProvisionLocked_RevertWhen_OperatorNotAllowed( + uint256 amount + ) public useIndexer useStake(amount) useLockedVerifier { + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, 0); + + vm.startPrank(users.operator); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingNotAuthorized(address,address,address)", + users.operator, + users.indexer, + subgraphDataServiceAddress + ); + vm.expectRevert(expectedError); + staking.provisionLocked( + users.indexer, + subgraphDataServiceAddress, + amount, + MAX_MAX_VERIFIER_CUT, + MAX_THAWING_PERIOD + ); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index f455ea041..c24429a1b 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -47,13 +47,11 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 verifierCutAmount, uint256 delegationAmount ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(false) { - // TODO: changePrank? - vm.stopPrank(); delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); - vm.startPrank(users.delegator); + resetPrank(users.delegator); _delegate(delegationAmount); vm.startPrank(subgraphDataServiceAddress); @@ -76,13 +74,11 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 verifierCutAmount, uint256 delegationAmount ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(true) { - // TODO: changePrank? - vm.stopPrank(); delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); - vm.startPrank(users.delegator); + resetPrank(users.delegator); _delegate(delegationAmount); vm.startPrank(subgraphDataServiceAddress); diff --git a/packages/horizon/test/utils/Utils.sol b/packages/horizon/test/utils/Utils.sol new file mode 100644 index 000000000..47e4e68df --- /dev/null +++ b/packages/horizon/test/utils/Utils.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +abstract contract Utils is Test { + /// @dev Stops the active prank and sets a new one. + function resetPrank(address msgSender) internal { + vm.stopPrank(); + vm.startPrank(msgSender); + } +} \ No newline at end of file From 5d7bb2213430cb54c5fc5e4a20dc31ad5276ea24 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 12:33:01 -0300 Subject: [PATCH 100/277] chore: legacy subgraph service tests --- packages/horizon/test/GraphBase.t.sol | 5 ++- .../horizon/test/staking/HorizonStaking.t.sol | 22 +++++----- .../test/staking/delegation/delegate.t.sol | 14 ++++++ .../test/staking/delegation/undelegate.t.sol | 31 ++++++++++--- .../test/staking/delegation/withdraw.t.sol | 44 ++++++++++++++----- .../test/staking/operator/locked.t.sol | 9 +++- .../test/staking/provision/locked.t.sol | 6 +-- .../horizon/test/staking/slash/slash.t.sol | 4 +- 8 files changed, 98 insertions(+), 37 deletions(-) diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index cc4924842..a517cc6a5 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -31,6 +31,7 @@ abstract contract GraphBaseTest is Utils, Constants { HorizonStaking private stakingBase; HorizonStakingExtension private stakingExtension; + address subgraphDataServiceLegacyAddress = makeAddr("subgraphDataServiceLegacyAddress"); address subgraphDataServiceAddress = makeAddr("subgraphDataServiceAddress"); /* Users */ @@ -137,12 +138,12 @@ abstract contract GraphBaseTest is Utils, Constants { ); stakingExtension = new HorizonStakingExtension( address(controller), - subgraphDataServiceAddress + subgraphDataServiceLegacyAddress ); stakingBase = new HorizonStaking( address(controller), address(stakingExtension), - subgraphDataServiceAddress + subgraphDataServiceLegacyAddress ); vm.stopPrank(); diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index cd2e9ba76..1c3a91c95 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -49,16 +49,16 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { vm.assume(delegationAmount > MIN_DELEGATION); vm.assume(delegationAmount <= 10_000_000_000 ether); vm.startPrank(users.delegator); - _delegate(delegationAmount); + _delegate(delegationAmount, subgraphDataServiceAddress); vm.startPrank(msgSender); _; } - modifier useLockedVerifier() { + modifier useLockedVerifier(address verifier) { address msgSender; (, msgSender,) = vm.readCallers(); resetPrank(users.governor); - staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); + staking.setAllowedLockedVerifier(verifier, true); resetPrank(msgSender); _; } @@ -76,20 +76,20 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { staking.deprovision(users.indexer, subgraphDataServiceAddress, nThawRequests); } - function _delegate(uint256 amount) internal { + function _delegate(uint256 amount, address verifier) internal { token.approve(address(staking), amount); - staking.delegate(users.indexer, subgraphDataServiceAddress, amount, 0); + staking.delegate(users.indexer, verifier, amount, 0); } - function _getDelegation() internal view returns (Delegation memory) { - return staking.getDelegation(users.indexer, subgraphDataServiceAddress, users.delegator); + function _getDelegation(address verifier) internal view returns (Delegation memory) { + return staking.getDelegation(users.indexer, verifier, users.delegator); } - function _undelegate(uint256 shares) internal { - staking.undelegate(users.indexer, subgraphDataServiceAddress, shares); + function _undelegate(uint256 shares, address verifier) internal { + staking.undelegate(users.indexer, verifier, shares); } - function _getDelegationPool() internal view returns (DelegationPool memory) { - return staking.getDelegationPool(users.indexer, subgraphDataServiceAddress); + function _getDelegationPool(address verifier) internal view returns (DelegationPool memory) { + return staking.getDelegationPool(users.indexer, verifier); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 58ae6f1e5..b779fce19 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -39,4 +39,18 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); } + + function testDelegate_LegacySubgraphService( + uint256 amount, + uint256 delegationAmount + ) public useIndexer { + amount = bound(amount, MIN_PROVISION_SIZE, 10_000_000_000 ether); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); + + resetPrank(users.delegator); + _delegate(delegationAmount, subgraphDataServiceLegacyAddress); + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceLegacyAddress); + assertEq(delegatedTokens, delegationAmount); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 99683c825..45f7850d7 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -14,8 +14,8 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 delegationAmount ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); - Delegation memory delegation = _getDelegation(); - _undelegate(delegation.shares); + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + _undelegate(delegation.shares, subgraphDataServiceAddress); LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceAddress, users.delegator); ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); @@ -30,7 +30,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { resetPrank(users.delegator); bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroShares()"); vm.expectRevert(expectedError); - _undelegate(0); + _undelegate(0, subgraphDataServiceAddress); } function testUndelegate_RevertWhen_OverUndelegation( @@ -39,7 +39,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 overDelegationShares ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); - Delegation memory delegation = _getDelegation(); + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); vm.assume(overDelegationShares > delegation.shares); bytes memory expectedError = abi.encodeWithSignature( @@ -48,7 +48,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { overDelegationShares ); vm.expectRevert(expectedError); - _undelegate(overDelegationShares); + _undelegate(overDelegationShares, subgraphDataServiceAddress); } function testUndelegate_RevertWhen_UndelegateLeavesInsufficientTokens( @@ -69,6 +69,25 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { MIN_DELEGATION ); vm.expectRevert(expectedError); - _undelegate(withdrawShares); + _undelegate(withdrawShares, subgraphDataServiceAddress); + } + + function testUndelegate_LegacySubgraphService( + uint256 amount, + uint256 delegationAmount + ) public useIndexer { + amount = bound(amount, MIN_PROVISION_SIZE, 10_000_000_000 ether); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); + + resetPrank(users.delegator); + _delegate(delegationAmount, subgraphDataServiceLegacyAddress); + Delegation memory delegation = _getDelegation(subgraphDataServiceLegacyAddress); + _undelegate(delegation.shares, subgraphDataServiceLegacyAddress); + + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceLegacyAddress, users.delegator); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + + assertEq(thawRequest.shares, delegation.shares); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 0b622ce9a..9490c19cf 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -12,27 +12,27 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { modifier useUndelegate(uint256 shares) { vm.stopPrank(); vm.startPrank(users.delegator); - Delegation memory delegation = _getDelegation(); + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); shares = bound(shares, 1, delegation.shares); if (shares != delegation.shares) { - DelegationPool memory pool = _getDelegationPool(); + DelegationPool memory pool = _getDelegationPool(subgraphDataServiceAddress); uint256 tokens = (shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 newTokensThawing = pool.tokensThawing + tokens; uint256 remainingTokens = (delegation.shares * (pool.tokens - newTokensThawing)) / pool.shares; vm.assume(remainingTokens >= MIN_DELEGATION); } - _undelegate(shares); + _undelegate(shares, subgraphDataServiceAddress); _; } - function _withdrawDelegated() private { - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0x0), 0, 0); + function _withdrawDelegated(address verifier) private { + staking.withdrawDelegated(users.indexer, verifier, address(0x0), 0, 0); } - function _expectedTokensFromThawRequest(ThawRequest memory thawRequest) private view returns (uint256) { - DelegationPool memory pool = _getDelegationPool(); + function _expectedTokensFromThawRequest(ThawRequest memory thawRequest, address verifier) private view returns (uint256) { + DelegationPool memory pool = _getDelegationPool(verifier); return (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing; } @@ -64,8 +64,8 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { skip(thawRequest.thawingUntil + 1); uint256 previousBalance = token.balanceOf(users.delegator); - uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest); - _withdrawDelegated(); + uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest, subgraphDataServiceAddress); + _withdrawDelegated(subgraphDataServiceAddress); uint256 newBalance = token.balanceOf(users.delegator); assertEq(newBalance - previousBalance, expectedTokens); @@ -81,7 +81,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - _withdrawDelegated(); + _withdrawDelegated(subgraphDataServiceAddress); } function testWithdrawDelegation_MoveToNewServiceProvider( @@ -118,7 +118,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useUndelegate(delegationAmount) { uint256 previousBalance = token.balanceOf(users.delegator); - _withdrawDelegated(); + _withdrawDelegated(subgraphDataServiceAddress); // Nothing changed since thawing period haven't finished uint256 newBalance = token.balanceOf(users.delegator); @@ -146,4 +146,26 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { uint256 delegatedTokens = staking.getDelegatedTokensAvailable(newIndexer, subgraphDataServiceAddress); assertEq(delegatedTokens, 0); } + + function testWithdrawDelegation_LegacySubgraphService(uint256 delegationAmount) public useIndexer { + delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + _createProvision(subgraphDataServiceLegacyAddress, 10_000_000 ether, 0, MAX_THAWING_PERIOD); + + resetPrank(users.delegator); + _delegate(delegationAmount, subgraphDataServiceLegacyAddress); + Delegation memory delegation = _getDelegation(subgraphDataServiceLegacyAddress); + _undelegate(delegation.shares, subgraphDataServiceLegacyAddress); + + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceLegacyAddress, users.delegator); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + + skip(thawRequest.thawingUntil + 1); + + uint256 previousBalance = token.balanceOf(users.delegator); + uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest, subgraphDataServiceLegacyAddress); + _withdrawDelegated(subgraphDataServiceLegacyAddress); + + uint256 newBalance = token.balanceOf(users.delegator); + assertEq(newBalance - previousBalance, expectedTokens); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/operator/locked.t.sol b/packages/horizon/test/staking/operator/locked.t.sol index b29d8890f..1f87004fb 100644 --- a/packages/horizon/test/staking/operator/locked.t.sol +++ b/packages/horizon/test/staking/operator/locked.t.sol @@ -7,7 +7,7 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingOperatorLockedTest is HorizonStakingTest { - function testOperatorLocked_Set() public useIndexer useLockedVerifier { + function testOperatorLocked_Set() public useIndexer useLockedVerifier(subgraphDataServiceAddress) { staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); } @@ -18,9 +18,14 @@ contract HorizonStakingOperatorLockedTest is HorizonStakingTest { staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); } - function testOperatorLocked_RevertWhen_CallerIsServiceProvider() public useIndexer useLockedVerifier { + function testOperatorLocked_RevertWhen_CallerIsServiceProvider() public useIndexer useLockedVerifier(subgraphDataServiceAddress) { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCallerIsServiceProvider()"); vm.expectRevert(expectedError); staking.setOperatorLocked(users.indexer, subgraphDataServiceAddress, true); } + + function testOperatorLocked_SetLegacySubgraphService() public useIndexer useLockedVerifier(subgraphDataServiceLegacyAddress) { + staking.setOperatorLocked(users.operator, subgraphDataServiceLegacyAddress, true); + assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceLegacyAddress)); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/locked.t.sol b/packages/horizon/test/staking/provision/locked.t.sol index 3560dad39..a4c826254 100644 --- a/packages/horizon/test/staking/provision/locked.t.sol +++ b/packages/horizon/test/staking/provision/locked.t.sol @@ -9,7 +9,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { function testProvisionLocked_Create( uint256 amount - ) public useIndexer useStake(amount) useLockedVerifier { + ) public useIndexer useStake(amount) useLockedVerifier(subgraphDataServiceAddress) { uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(provisionTokens, 0); @@ -30,7 +30,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { function testProvisionLocked_RevertWhen_VerifierNotAllowed( uint256 amount - ) public useIndexer useStake(amount) useLockedVerifier { + ) public useIndexer useStake(amount) useLockedVerifier(subgraphDataServiceAddress) { uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(provisionTokens, 0); @@ -55,7 +55,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { function testProvisionLocked_RevertWhen_OperatorNotAllowed( uint256 amount - ) public useIndexer useStake(amount) useLockedVerifier { + ) public useIndexer useStake(amount) useLockedVerifier(subgraphDataServiceAddress) { uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(provisionTokens, 0); diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index c24429a1b..5d1ab96d6 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -52,7 +52,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); resetPrank(users.delegator); - _delegate(delegationAmount); + _delegate(delegationAmount, subgraphDataServiceAddress); vm.startPrank(subgraphDataServiceAddress); _slash(slashAmount, verifierCutAmount); @@ -79,7 +79,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); resetPrank(users.delegator); - _delegate(delegationAmount); + _delegate(delegationAmount, subgraphDataServiceAddress); vm.startPrank(subgraphDataServiceAddress); _slash(slashAmount, verifierCutAmount); From 0ebdbae100bf04bd148874eccf2ab130989c7090 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 12:59:29 -0300 Subject: [PATCH 101/277] chore: deployments tests --- packages/horizon/test/GraphBase.t.sol | 2 +- .../test/deployments/Deployments.t.sol | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index a517cc6a5..def11a81a 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -123,7 +123,7 @@ abstract contract GraphBaseTest is Utils, Constants { controller.setContractProxy(keccak256("Curation"), makeAddr("Curation")); controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); controller.setContractProxy(keccak256("BridgeEscrow"), makeAddr("BridgeEscrow")); - controller.setContractProxy(keccak256("GraphProxyAdmin"), makeAddr("GraphProxyAdmin")); + controller.setContractProxy(keccak256("GraphProxyAdmin"), address(proxyAdmin)); vm.stopPrank(); vm.startPrank(users.deployer); diff --git a/packages/horizon/test/deployments/Deployments.t.sol b/packages/horizon/test/deployments/Deployments.t.sol index 46abde654..f3c088ab7 100644 --- a/packages/horizon/test/deployments/Deployments.t.sol +++ b/packages/horizon/test/deployments/Deployments.t.sol @@ -7,11 +7,23 @@ import { GraphBaseTest } from "../GraphBase.t.sol"; contract GraphDeploymentsTest is GraphBaseTest { + /* + * HELPERS + */ + + function _getContractFromController(bytes memory _contractName) private view returns (address) { + return controller.getContractProxy(keccak256(_contractName)); + } + + /* + * TESTS + */ + function testDeployments() public view { - // assertEq(address(escrow.GRAPH_PAYMENTS()), address(payments)); - // assertEq(address(escrow.GRAPH_TOKEN()), address(token)); - // assertEq(address(payments.STAKING()), address(staking)); - // assertEq(address(payments.GRAPH_ESCROW()), address(escrow)); - // assertEq(address(payments.GRAPH_TOKEN()), address(token)); + assertEq(_getContractFromController("GraphPayments"), address(payments)); + assertEq(_getContractFromController("GraphToken"), address(token)); + assertEq(_getContractFromController("Staking"), address(staking)); + assertEq(_getContractFromController("PaymentsEscrow"), address(escrow)); + assertEq(_getContractFromController("GraphProxyAdmin"), address(proxyAdmin)); } } From 646198e05187bbad6cca83f569053166a9944a81 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 13:10:30 -0300 Subject: [PATCH 102/277] chore: comments heading --- packages/horizon/test/GraphBase.t.sol | 12 ++++++++++-- packages/horizon/test/escrow/GraphEscrow.t.sol | 10 +++++++--- packages/horizon/test/escrow/collect.t.sol | 4 ++++ packages/horizon/test/escrow/collector.t.sol | 10 +++------- packages/horizon/test/escrow/deposit.t.sol | 4 ++++ packages/horizon/test/escrow/thaw.t.sol | 4 ++++ packages/horizon/test/escrow/withdraw.t.sol | 8 ++++++++ packages/horizon/test/payments/GraphPayments.t.sol | 4 ++++ .../horizon-staking/HorizonStakingShared.t.sol | 14 +++++++------- packages/horizon/test/staking/HorizonStaking.t.sol | 8 ++++++++ .../horizon/test/staking/delegation/delegate.t.sol | 4 ++++ .../test/staking/delegation/undelegate.t.sol | 4 ++++ .../horizon/test/staking/delegation/withdraw.t.sol | 12 ++++++++++++ .../test/staking/governance/governance.t.sol | 8 ++++++++ .../horizon/test/staking/operator/locked.t.sol | 4 ++++ .../horizon/test/staking/operator/operator.t.sol | 4 ++++ .../test/staking/provision/deprovision.t.sol | 4 ++++ .../horizon/test/staking/provision/locked.t.sol | 4 ++++ .../horizon/test/staking/provision/provision.t.sol | 4 ++++ .../test/staking/provision/reprovision.t.sol | 12 ++++++++++++ packages/horizon/test/staking/slash/slash.t.sol | 12 ++++++++++++ packages/horizon/test/staking/stake/stake.t.sol | 4 ++++ packages/horizon/test/staking/stake/unstake.t.sol | 4 ++++ packages/horizon/test/staking/thaw/thaw.t.sol | 5 +++++ 24 files changed, 144 insertions(+), 19 deletions(-) diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index def11a81a..e21a13142 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -19,6 +19,10 @@ import { Utils } from "./utils/Utils.sol"; abstract contract GraphBaseTest is Utils, Constants { + /* + * VARIABLES + */ + /* Contracts */ GraphProxyAdmin public proxyAdmin; @@ -42,7 +46,9 @@ abstract contract GraphBaseTest is Utils, Constants { Constants public constants; - /* Set Up */ + /* + * SET UP + */ function setUp() public virtual { // Deploy ERC20 token @@ -171,7 +177,9 @@ abstract contract GraphBaseTest is Utils, Constants { return user; } - /* Token helpers */ + /* + * TOKEN HELPERS + */ function mint(address _address, uint256 amount) internal { deal({ token: address(token), to: _address, give: amount }); diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index 5d0e01954..bad127890 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaki contract GraphEscrowTest is HorizonStakingSharedTest { + /* + * MODIFIERS + */ + modifier useGateway() { vm.startPrank(users.gateway); _; @@ -31,9 +35,9 @@ contract GraphEscrowTest is HorizonStakingSharedTest { _; } - function setUp() public virtual override { - HorizonStakingSharedTest.setUp(); - } + /* + * HELPERS + */ function _depositTokens(uint256 tokens) internal { token.approve(address(escrow), tokens); diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 5a9a71fa1..ab6808f55 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -8,6 +8,10 @@ import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; contract GraphEscrowCollectTest is GraphEscrowTest { + /* + * TESTS + */ + function testCollect_Tokens( uint256 amount, uint256 tokensDataService diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index 83d7fb42a..3c13b1b42 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -7,7 +7,9 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowCollectorTest is GraphEscrowTest { - // Collector approve tests + /* + * TESTS + */ function testCollector_Approve(uint256 amount) public useGateway useCollector(amount) { (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); @@ -25,8 +27,6 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { escrow.approveCollector(users.verifier, smallerAmount); } - // Collector thaw tests - function testCollector_Thaw(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); @@ -35,8 +35,6 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); } - // Collector cancel thaw tests - function testCollector_CancelThaw(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); @@ -58,8 +56,6 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { vm.stopPrank(); } - // Collector revoke tests - function testCollector_Revoke(uint256 amount) public useGateway useCollector(amount) { escrow.thawCollector(users.verifier); skip(revokeCollectorThawingPeriod + 1); diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol index 8e9839b9b..79b7c3616 100644 --- a/packages/horizon/test/escrow/deposit.t.sol +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -7,6 +7,10 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowDepositTest is GraphEscrowTest { + /* + * TESTS + */ + function testDeposit_Tokens(uint256 amount) public useGateway useDeposit(amount) { (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); assertEq(indexerEscrowBalance, amount); diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 1b952e1f1..60bf343e0 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -7,6 +7,10 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowThawTest is GraphEscrowTest { + /* + * TESTS + */ + function testThaw_Tokens(uint256 amount) public useGateway useDeposit(amount) { escrow.thaw(users.indexer, amount); diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index a541c818b..d2561f418 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -7,6 +7,10 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowWithdrawTest is GraphEscrowTest { + /* + * MODIFIERS + */ + modifier depositAndThawTokens(uint256 amount, uint256 thawAmount) { vm.assume(thawAmount > 0); vm.assume(amount > thawAmount); @@ -15,6 +19,10 @@ contract GraphEscrowWithdrawTest is GraphEscrowTest { _; } + /* + * TESTS + */ + function testWithdraw_Tokens( uint256 amount, uint256 thawAmount diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 70806f42f..dcbdf82fb 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -9,6 +9,10 @@ import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaki contract GraphPaymentsTest is HorizonStakingSharedTest { + /* + * TESTS + */ + function testCollect( uint256 amount, uint256 tokensDataService diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 2ee0d5764..363587d26 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -8,6 +8,10 @@ import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol abstract contract HorizonStakingSharedTest is GraphBaseTest { + /* + * MODIFIERS + */ + modifier useIndexer() { vm.startPrank(users.indexer); _; @@ -34,13 +38,9 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { _; } - /* Set Up */ - - function setUp() public virtual override { - GraphBaseTest.setUp(); - } - - /* Helpers */ + /* + * HELPERS + */ function _createProvision( address dataServiceAddress, diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index 1c3a91c95..383639ae7 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -8,6 +8,10 @@ import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaki contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { + /* + * MODIFIERS + */ + modifier useOperator() { vm.startPrank(users.indexer); staking.setOperator(users.operator, subgraphDataServiceAddress, true); @@ -63,6 +67,10 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { _; } + /* + * HELPERS + */ + function _stakeTo(address to, uint256 amount) internal { approve(address(staking), amount); staking.stakeTo(to, amount); diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index b779fce19..504164807 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDelegateTest is HorizonStakingTest { + /* + * TESTS + */ + function testDelegate_Tokens( uint256 amount, uint256 delegationAmount diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 45f7850d7..40a01a490 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -9,6 +9,10 @@ import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; contract HorizonStakingUndelegateTest is HorizonStakingTest { + /* + * TESTS + */ + function testUndelegate_Tokens( uint256 amount, uint256 delegationAmount diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 9490c19cf..9c9e862f7 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -9,6 +9,10 @@ import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { + /* + * MODIFIERS + */ + modifier useUndelegate(uint256 shares) { vm.stopPrank(); vm.startPrank(users.delegator); @@ -27,6 +31,10 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { _; } + /* + * HELPERS + */ + function _withdrawDelegated(address verifier) private { staking.withdrawDelegated(users.indexer, verifier, address(0x0), 0, 0); } @@ -48,6 +56,10 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { return newIndexer; } + /* + * TESTS + */ + function testWithdrawDelegation_Tokens( uint256 delegationAmount, uint256 withdrawShares diff --git a/packages/horizon/test/staking/governance/governance.t.sol b/packages/horizon/test/staking/governance/governance.t.sol index 078d39ba2..430ad69a0 100644 --- a/packages/horizon/test/staking/governance/governance.t.sol +++ b/packages/horizon/test/staking/governance/governance.t.sol @@ -7,11 +7,19 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingGovernanceTest is HorizonStakingTest { + /* + * MODIFIERS + */ + modifier useGovernor { vm.startPrank(users.governor); _; } + /* + * TESTS + */ + function testGovernance_SetAllowedLockedVerifier() public useGovernor { staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); assertTrue(staking.isAllowedLockedVerifier(subgraphDataServiceAddress)); diff --git a/packages/horizon/test/staking/operator/locked.t.sol b/packages/horizon/test/staking/operator/locked.t.sol index 1f87004fb..e6eb8038d 100644 --- a/packages/horizon/test/staking/operator/locked.t.sol +++ b/packages/horizon/test/staking/operator/locked.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingOperatorLockedTest is HorizonStakingTest { + /* + * TESTS + */ + function testOperatorLocked_Set() public useIndexer useLockedVerifier(subgraphDataServiceAddress) { staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); diff --git a/packages/horizon/test/staking/operator/operator.t.sol b/packages/horizon/test/staking/operator/operator.t.sol index 034acdf8e..af06e0ef5 100644 --- a/packages/horizon/test/staking/operator/operator.t.sol +++ b/packages/horizon/test/staking/operator/operator.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingOperatorTest is HorizonStakingTest { + /* + * TESTS + */ + function testOperator_SetOperator() public useOperator { assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); } diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index a187dfc6b..9f3438739 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDeprovisionTest is HorizonStakingTest { + /* + * TESTS + */ + function testDeprovision_AllRequests( uint256 amount, uint32 maxVerifierCut, diff --git a/packages/horizon/test/staking/provision/locked.t.sol b/packages/horizon/test/staking/provision/locked.t.sol index a4c826254..642ba9a10 100644 --- a/packages/horizon/test/staking/provision/locked.t.sol +++ b/packages/horizon/test/staking/provision/locked.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingProvisionLockedTest is HorizonStakingTest { + /* + * TESTS + */ + function testProvisionLocked_Create( uint256 amount ) public useIndexer useStake(amount) useLockedVerifier(subgraphDataServiceAddress) { diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index bb5f4792a..823a87d54 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingProvisionTest is HorizonStakingTest { + /* + * TESTS + */ + function testProvision_Create( uint256 amount, uint32 maxVerifierCut, diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 06c033888..3d1d803dc 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -7,12 +7,24 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingReprovisionTest is HorizonStakingTest { + /* + * VARIABLES + */ + address private newDataService = makeAddr("newDataService"); + /* + * HELPERS + */ + function _reprovision(uint256 tokens, uint256 nThawRequests) private { staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, tokens, nThawRequests); } + /* + * TESTS + */ + function testReprovision_MovingTokens( uint64 thawingPeriod, uint256 provisionAmount diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 5d1ab96d6..6cd2563f6 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingSlashTest is HorizonStakingTest { + /* + * MODIFIERS + */ + modifier useDelegationSlashing(bool enabled) { address msgSender; (, msgSender,) = vm.readCallers(); @@ -16,10 +20,18 @@ contract HorizonStakingSlashTest is HorizonStakingTest { _; } + /* + * HELPERS + */ + function _slash(uint256 amount, uint256 verifierCutAmount) private { staking.slash(users.indexer, amount, verifierCutAmount, subgraphDataServiceAddress); } + /* + * TESTS + */ + function testSlash_Tokens( uint256 amount, uint32 maxVerifierCut, diff --git a/packages/horizon/test/staking/stake/stake.t.sol b/packages/horizon/test/staking/stake/stake.t.sol index 048d6b4a7..9c1c69ad9 100644 --- a/packages/horizon/test/staking/stake/stake.t.sol +++ b/packages/horizon/test/staking/stake/stake.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingStakeTest is HorizonStakingTest { + /* + * TESTS + */ + function testStake_Tokens(uint256 amount) public useIndexer useStake(amount) { assertTrue(staking.getStake(address(users.indexer)) == amount); } diff --git a/packages/horizon/test/staking/stake/unstake.t.sol b/packages/horizon/test/staking/stake/unstake.t.sol index 56eac4bfb..140148d24 100644 --- a/packages/horizon/test/staking/stake/unstake.t.sol +++ b/packages/horizon/test/staking/stake/unstake.t.sol @@ -7,6 +7,10 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingUnstakeTest is HorizonStakingTest { + /* + * TESTS + */ + function testUnstake_Tokens( uint256 amount, uint32 maxVerifierCut, diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index 6a4a475f0..1f747f7f0 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -7,6 +7,11 @@ import { IHorizonStakingTypes } from "../../../contracts/interfaces/internal/IHo import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingThawTest is HorizonStakingTest { + + /* + * TESTS + */ + function testThaw_Tokens( uint256 amount, uint64 thawingPeriod, From 352d7f1ea1f5e6a6efeb502e7f741b7fd6476b11 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 15:08:33 -0300 Subject: [PATCH 103/277] chore: staking service provider tests --- .../horizon/test/escrow/GraphEscrow.t.sol | 2 +- .../horizon/test/payments/GraphPayments.t.sol | 2 +- .../HorizonStakingShared.t.sol | 4 +- .../horizon/test/staking/HorizonStaking.t.sol | 2 +- .../test/staking/delegation/delegate.t.sol | 4 +- .../test/staking/delegation/undelegate.t.sol | 4 +- .../test/staking/delegation/withdraw.t.sol | 2 +- .../serviceProvider/serviceProvider.t.sol | 107 ++++++++++++++++++ .../horizon/test/staking/slash/slash.t.sol | 4 +- packages/horizon/test/utils/Constants.sol | 1 + 10 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index bad127890..c94d221df 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -24,7 +24,7 @@ contract GraphEscrowTest is HorizonStakingSharedTest { modifier useDeposit(uint256 tokens) { vm.assume(tokens > 0); - vm.assume(tokens <= 10_000_000_000 ether); + vm.assume(tokens <= MAX_STAKING_TOKENS); _depositTokens(tokens); _; } diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index dcbdf82fb..637caba61 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -47,7 +47,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { uint256 amount, uint256 tokensDataService ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { - vm.assume(tokensDataService <= 10_000_000_000 ether); + vm.assume(tokensDataService <= MAX_STAKING_TOKENS); vm.assume(tokensDataService > amount); address escrowAddress = address(escrow); diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 363587d26..85cbbcbaf 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -20,12 +20,12 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { modifier assumeProvisionTokens(uint256 tokens) { vm.assume(tokens > MIN_PROVISION_SIZE); - vm.assume(tokens <= 10_000_000_000 ether); + vm.assume(tokens <= MAX_STAKING_TOKENS); _; } modifier useProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) { - vm.assume(tokens <= 10_000_000_000 ether); + vm.assume(tokens <= MAX_STAKING_TOKENS); vm.assume(tokens > MIN_PROVISION_SIZE); vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index 383639ae7..e74db32ce 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -51,7 +51,7 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { address msgSender; (, msgSender,) = vm.readCallers(); vm.assume(delegationAmount > MIN_DELEGATION); - vm.assume(delegationAmount <= 10_000_000_000 ether); + vm.assume(delegationAmount <= MAX_STAKING_TOKENS); vm.startPrank(users.delegator); _delegate(delegationAmount, subgraphDataServiceAddress); vm.startPrank(msgSender); diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 504164807..708c3bf5c 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -48,8 +48,8 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount ) public useIndexer { - amount = bound(amount, MIN_PROVISION_SIZE, 10_000_000_000 ether); - delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + amount = bound(amount, MIN_PROVISION_SIZE, MAX_STAKING_TOKENS); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 40a01a490..ec37d8112 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -80,8 +80,8 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount ) public useIndexer { - amount = bound(amount, MIN_PROVISION_SIZE, 10_000_000_000 ether); - delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + amount = bound(amount, MIN_PROVISION_SIZE, MAX_STAKING_TOKENS); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 9c9e862f7..8110c3d9a 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -160,7 +160,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { } function testWithdrawDelegation_LegacySubgraphService(uint256 delegationAmount) public useIndexer { - delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); _createProvision(subgraphDataServiceLegacyAddress, 10_000_000 ether, 0, MAX_THAWING_PERIOD); resetPrank(users.delegator); diff --git a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol new file mode 100644 index 000000000..9a1885e87 --- /dev/null +++ b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol"; + +contract HorizonStakingServiceProviderTest is HorizonStakingTest { + + /* + * TESTS + */ + + function testServiceProvider_GetProvider( + uint256 amount, + uint256 operatorAmount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + operatorAmount = bound(operatorAmount, 1, MAX_STAKING_TOKENS); + ServiceProvider memory sp = staking.getServiceProvider(users.indexer); + assertEq(sp.tokensStaked, amount); + assertEq(sp.tokensProvisioned, amount); + + staking.setOperator(users.operator, subgraphDataServiceAddress, true); + resetPrank(users.operator); + _stakeTo(users.indexer, operatorAmount); + sp = staking.getServiceProvider(users.indexer); + assertEq(sp.tokensStaked, amount + operatorAmount); + assertEq(sp.tokensProvisioned, amount); + } + + function testServiceProvider_GetDelegationFeeCut( + uint256 queryCut, + uint256 indexingCut, + uint256 rewardsCut + ) public useIndexer { + _setDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, queryCut); + _setDelegationFeeCut(IGraphPayments.PaymentTypes.IndexingFee, indexingCut); + _setDelegationFeeCut(IGraphPayments.PaymentTypes.IndexingRewards, rewardsCut); + + uint256 queryFeeCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, IGraphPayments.PaymentTypes.QueryFee); + uint256 indexingFeeCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, IGraphPayments.PaymentTypes.IndexingFee); + uint256 indexingRewardsCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, IGraphPayments.PaymentTypes.IndexingRewards); + assertEq(queryFeeCut, queryCut); + assertEq(indexingFeeCut, indexingCut); + assertEq(indexingRewardsCut, rewardsCut); + } + + function testServiceProvider_GetProvision( + uint256 amount, + uint256 thawAmount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + thawAmount = bound(thawAmount, 1, amount); + Provision memory p = staking.getProvision(users.indexer, subgraphDataServiceAddress); + assertEq(p.tokens, amount); + assertEq(p.tokensThawing, 0); + assertEq(p.sharesThawing, 0); + assertEq(p.maxVerifierCut, maxVerifierCut); + assertEq(p.thawingPeriod, thawingPeriod); + assertEq(p.createdAt, block.timestamp); + assertEq(p.maxVerifierCutPending, maxVerifierCut); + assertEq(p.thawingPeriodPending, thawingPeriod); + + staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + p = staking.getProvision(users.indexer, subgraphDataServiceAddress); + assertEq(p.tokensThawing, thawAmount); + } + + function testServiceProvider_GetTokensAvailable( + uint256 amount, + uint256 thawAmount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + thawAmount = bound(thawAmount, 1, amount); + uint256 tokensAvailable = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, 0); + assertEq(tokensAvailable, amount); + + staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + tokensAvailable = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, 0); + assertEq(tokensAvailable, amount - thawAmount); + } + + function testServiceProvider_GetTokensAvailable_WithDelegation( + uint256 amount, + uint256 delegationAmount, + uint32 delegationRatio + ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { + uint256 tokensAvailable = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, delegationRatio); + + uint256 tokensDelegatedMax = amount * (uint256(delegationRatio)); + uint256 tokensDelegatedCapacity = delegationAmount > tokensDelegatedMax ? tokensDelegatedMax : delegationAmount; + assertEq(tokensAvailable, amount + tokensDelegatedCapacity); + } + + function testServiceProvider_GetProviderTokensAvailable( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { + uint256 providerTokensAvailable = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(providerTokensAvailable, amount); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 6cd2563f6..50f4d1e88 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -59,7 +59,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 verifierCutAmount, uint256 delegationAmount ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(false) { - delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); @@ -86,7 +86,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 verifierCutAmount, uint256 delegationAmount ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(true) { - delegationAmount = bound(delegationAmount, MIN_DELEGATION, 10_000_000_000 ether); + delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index 00c253bbd..46445b039 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; abstract contract Constants { uint256 internal constant MAX_PPM = 1000000; // 100% in parts per million uint256 internal constant delegationFeeCut = 100000; // 10% in parts per million + uint256 internal constant MAX_STAKING_TOKENS = 10_000_000_000 ether; // GraphEscrow parameters uint256 internal constant withdrawEscrowThawingPeriod = 60; uint256 internal constant revokeCollectorThawingPeriod = 60; From cec263910cc90e2dfa692961768d0d04c32b89ff Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 15:33:23 -0300 Subject: [PATCH 104/277] fix: vm.assume rejecting too many options --- packages/horizon/test/payments/GraphPayments.t.sol | 3 +-- packages/horizon/test/staking/delegation/undelegate.t.sol | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 637caba61..0a53f5e20 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -47,8 +47,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { uint256 amount, uint256 tokensDataService ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { - vm.assume(tokensDataService <= MAX_STAKING_TOKENS); - vm.assume(tokensDataService > amount); + tokensDataService = bound(tokensDataService, amount + 1, MAX_STAKING_TOKENS); address escrowAddress = address(escrow); mint(escrowAddress, amount); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index ec37d8112..9b74f729d 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -44,7 +44,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); - vm.assume(overDelegationShares > delegation.shares); + overDelegationShares = bound(overDelegationShares, delegation.shares + 1, MAX_STAKING_TOKENS); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientShares(uint256,uint256)", From c26e06bc88d113db1352027fb6c9564450d85581 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 15:33:46 -0300 Subject: [PATCH 105/277] chore: add set staking counterpart address --- .../test/staking/governance/governance.t.sol | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/horizon/test/staking/governance/governance.t.sol b/packages/horizon/test/staking/governance/governance.t.sol index 430ad69a0..71cd1bb49 100644 --- a/packages/horizon/test/staking/governance/governance.t.sol +++ b/packages/horizon/test/staking/governance/governance.t.sol @@ -66,4 +66,19 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); } + + function testGovernance_SetCounterpartStakingAddress(address counterpartStakingAddress) public useGovernor { + staking.setCounterpartStakingAddress(counterpartStakingAddress); + bytes32 storedValue = vm.load(address(staking), bytes32(uint256(24))); + address storedCounterpartStakingAddress = address(uint160(uint256(storedValue))); + assertEq(storedCounterpartStakingAddress, counterpartStakingAddress); + } + + function testGovernance_RevertWhen_SetCounterpartStakingAddress_NotGovernor( + address counterpartStakingAddress + ) public useIndexer { + bytes memory expectedError = abi.encodeWithSignature("ManagedOnlyGovernor()"); + vm.expectRevert(expectedError); + staking.setCounterpartStakingAddress(counterpartStakingAddress); + } } \ No newline at end of file From d109bbc390cc4cb729bd66c3cbd27f77608449d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 4 Jun 2024 16:19:04 -0300 Subject: [PATCH 106/277] test: add tests for linked list library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServiceFees.sol | 7 +- .../contracts/libraries/LinkedList.sol | 30 ++- .../contracts/staking/HorizonStaking.sol | 7 +- packages/horizon/test/data-service/DataS.sol | 83 -------- packages/horizon/test/data-service/test.t.sol | 30 --- .../horizon/test/libraries/LinkedList.t.sol | 180 ++++++++++++++++++ .../horizon/test/libraries/LinkedList.tree | 34 ++++ .../test/libraries/ListImplementation.sol | 48 +++++ .../horizon/test/staking/HorizonStaking.t.sol | 2 +- 9 files changed, 291 insertions(+), 130 deletions(-) delete mode 100644 packages/horizon/test/data-service/DataS.sol delete mode 100644 packages/horizon/test/data-service/test.t.sol create mode 100644 packages/horizon/test/libraries/LinkedList.t.sol create mode 100644 packages/horizon/test/libraries/LinkedList.tree create mode 100644 packages/horizon/test/libraries/ListImplementation.sol diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 000a72d09..1c81da824 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -79,15 +79,14 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat * @param _claimId The id of the stake claim * @param _acc The accumulator for the stake claims being processed * @return Wether the stake claim is still locked, indicating that the traversal should continue or stop. - * @return Wether the stake claim should be deleted * @return The updated accumulator data */ - function _processStakeClaim(bytes32 _claimId, bytes memory _acc) private returns (bool, bool, bytes memory) { + function _processStakeClaim(bytes32 _claimId, bytes memory _acc) private returns (bool, bytes memory) { StakeClaim memory claim = _getStakeClaim(_claimId); // early exit if (claim.releaseAt > block.timestamp) { - return (true, false, LinkedList.NULL_BYTES); + return (true, LinkedList.NULL_BYTES); } // decode @@ -99,7 +98,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat // encode _acc = abi.encode(tokensClaimed + claim.tokens, serviceProvider); - return (false, true, _acc); + return (false, _acc); } /** diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index 99bf682ea..7a49d0c5a 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -11,6 +11,7 @@ pragma solidity 0.8.26; * - they must be represented by a unique bytes32 id * - the id of the item must not be bytes32(0) * - each item must have a reference to the next item in the list + * - the list cannot have more than `MAX_ITEMS` items * * A contract using this library must store: * - a LinkedList.List to keep track of the list metadata @@ -34,20 +35,36 @@ library LinkedList { /// @notice Empty bytes constant bytes internal constant NULL_BYTES = bytes(""); + /// @notice Maximum amount of items allowed in the list + uint256 internal constant MAX_ITEMS = 10_000; + /** * @notice Thrown when trying to remove an item from an empty list */ error LinkedListEmptyList(); + /** + * @notice Thrown when trying to add an item to a list that has reached the maximum number of elements + */ + error LinkedListMaxElementsExceeded(); + + /** + * @notice Thrown when trying to traverse a list with more iterations than elements + */ + error LinkedListInvalidIterations(); + /** * @notice Adds an item to the list. * The item is added to the end of the list. * @dev Note that this function will not take care of linking the * old tail to the new item. The caller should take care of this. + * It will also not ensure id uniqueness. + * @dev There is a maximum number of elements that can be added to the list. * @param self The list metadata * @param id The id of the item to add */ function add(List storage self, bytes32 id) internal { + require(self.count < MAX_ITEMS, LinkedListMaxElementsExceeded()); self.tail = id; self.nonce += 1; if (self.count == 0) self.head = id; @@ -96,11 +113,13 @@ library LinkedList { function traverse( List storage self, function(bytes32) view returns (bytes32) getNextItem, - function(bytes32, bytes memory) returns (bool, bool, bytes memory) processItem, + function(bytes32, bytes memory) returns (bool, bytes memory) processItem, function(bytes32) deleteItem, bytes memory processInitAcc, uint256 iterations ) internal returns (uint256, bytes memory) { + require(iterations <= self.count, LinkedListInvalidIterations()); + uint256 itemCount = 0; bool traverseAll = iterations == 0; bytes memory acc = processInitAcc; @@ -108,17 +127,12 @@ library LinkedList { bytes32 cursor = self.head; while (cursor != bytes32(0) && (traverseAll || iterations > 0)) { - (bool shouldBreak, bool shouldDelete, bytes memory acc_) = processItem(cursor, acc); + (bool shouldBreak, bytes memory acc_) = processItem(cursor, acc); if (shouldBreak) break; acc = acc_; - - if (shouldDelete) { - cursor = self.remove(getNextItem, deleteItem); - } else { - cursor = getNextItem(cursor); - } + cursor = self.remove(getNextItem, deleteItem); if (!traverseAll) iterations--; itemCount++; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 3ffc3e4b6..c8d7f437f 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -886,15 +886,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param _thawRequestId The ID of the current thaw request * @param _acc The accumulator data for the thaw requests being fulfilled * @return Wether the thaw request is still thawing, indicating that the traversal should continue or stop. - * @return Wether the thaw request should be deleted * @return The updated accumulator data */ - function _fulfillThawRequest(bytes32 _thawRequestId, bytes memory _acc) private returns (bool, bool, bytes memory) { + function _fulfillThawRequest(bytes32 _thawRequestId, bytes memory _acc) private returns (bool, bytes memory) { ThawRequest storage thawRequest = _thawRequests[_thawRequestId]; // early exit if (thawRequest.thawingUntil > block.timestamp) { - return (true, false, LinkedList.NULL_BYTES); + return (true, LinkedList.NULL_BYTES); } // decode @@ -912,7 +911,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { // encode _acc = abi.encode(tokensThawed, tokensThawing, sharesThawing); - return (false, true, _acc); + return (false, _acc); } /** diff --git a/packages/horizon/test/data-service/DataS.sol b/packages/horizon/test/data-service/DataS.sol deleted file mode 100644 index 3ed3aa3ba..000000000 --- a/packages/horizon/test/data-service/DataS.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; -import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; -import { IDataServiceFees } from "../../contracts/data-service/interfaces/IDataServiceFees.sol"; - -import { LinkedList } from "../../contracts/libraries/LinkedList.sol"; -import "forge-std/console.sol"; - -contract DataS { - using LinkedList for LinkedList.List; - struct StakeClaim { - uint256 tokens; - uint256 releaseAt; - bytes32 nextClaim; - } - - mapping(bytes32 claimId => StakeClaim tokens) public claims; - /// @notice Service providers registered in the data service - mapping(address serviceProvider => LinkedList.List list) public claimsLists2; - - constructor() {} - - function lockStake(address sp, uint256 tokens, uint256 unlock) external { - _lockStake(sp, tokens, unlock); - } - - function releaseStake2(address _serviceProvider, uint256 _n) external { - LinkedList.List storage claimsList2 = claimsLists2[_serviceProvider]; - (uint256 count, bytes memory acc) = claimsList2.traverse( - _getNextStakeClaim, - _processStakeClaim, - _deleteStakeClaim, - abi.encode(0), - _n - ); - - uint256 tokens = abi.decode(acc, (uint256)); - - console.log("count: %s", count); - console.log("tokens accumualted: %s", tokens); - } - - function _lockStake(address _serviceProvider, uint256 _tokens, uint256 _unlockTimestamp) internal { - LinkedList.List storage claimsList = claimsLists2[_serviceProvider]; - bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce); - claims[claimId] = StakeClaim({ tokens: _tokens, releaseAt: _unlockTimestamp, nextClaim: bytes32(0) }); - console.logBytes32(claimId); - claims[claimsList.tail].nextClaim = claimId; - - claimsList.tail = claimId; - claimsList.nonce += 1; - if (claimsList.head == bytes32(0)) claimsList.head = claimId; - } - - function _buildStakeClaimId(address _serviceProvider, uint256 _nonce) private view returns (bytes32) { - return keccak256(abi.encodePacked(address(this), _serviceProvider, _nonce)); - } - - function _getStakeClaim(bytes32 _claimId) private view returns (StakeClaim memory) { - StakeClaim memory claim = claims[_claimId]; - return claim; - } - - function _getNextStakeClaim(bytes32 _claimId) private view returns (bytes32) { - StakeClaim memory claim = claims[_claimId]; - return claim.nextClaim; - } - - function _deleteStakeClaim(bytes32 _claimId) private { - delete claims[_claimId]; - } - - function _processStakeClaim( - bytes32 _claimId, - bytes memory acc_ - ) private returns (bool, bool, bytes memory) { - StakeClaim memory claim = _getStakeClaim(_claimId); - if (block.timestamp < claim.releaseAt) return (true, false, LinkedList.NULL_BYTES); - - uint256 tokensAcc = abi.decode(acc_, (uint256)); - return (block.timestamp < claim.releaseAt, true, abi.encode(tokensAcc + claim.tokens)); - } -} diff --git a/packages/horizon/test/data-service/test.t.sol b/packages/horizon/test/data-service/test.t.sol deleted file mode 100644 index ddedca6c7..000000000 --- a/packages/horizon/test/data-service/test.t.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { DataS } from "./DataS.sol"; - -// import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaking.t.sol"; - -contract DataServiceTest is Test { - DataS ds = new DataS(); - address sp1 = makeAddr("sp1"); - - function setUp() public { - ds.lockStake(sp1, 10 wei, block.timestamp + 100); - ds.lockStake(sp1, 1 wei, block.timestamp + 200); - ds.lockStake(sp1, 1 wei, block.timestamp + 300); - ds.lockStake(sp1, 1 wei, block.timestamp + 400); - vm.warp(block.timestamp + 2000); - console.log("done setup"); - } - - function test_test() public { - assertTrue(true); - } - - function test_release() public { - ds.releaseStake2(sp1, 0); - } -} diff --git a/packages/horizon/test/libraries/LinkedList.t.sol b/packages/horizon/test/libraries/LinkedList.t.sol new file mode 100644 index 000000000..63229fb2c --- /dev/null +++ b/packages/horizon/test/libraries/LinkedList.t.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "forge-std/console.sol"; +import {Test} from "forge-std/Test.sol"; +import {LinkedList} from "../../contracts/libraries/LinkedList.sol"; + +import {ListImplementation} from "./ListImplementation.sol"; + +contract LinkedListTest is Test, ListImplementation { + using LinkedList for LinkedList.List; + + function setUp() internal { + list = LinkedList.List({head: bytes32(0), tail: bytes32(0), nonce: 0, count: 0}); + } + + function test_Add_GivenTheListIsEmpty() external { + _assert_addItem(_buildItemId(list.nonce), 0); + } + + function test_Add_GivenTheListIsNotEmpty() external { + // init list + _assert_addItem(_buildItemId(list.nonce), 0); + + // add to a non empty list + _assert_addItem(_buildItemId(list.nonce), 1); + } + + function test_Add_RevertGiven_TheListIsAtMaxSize() external { + for (uint256 i = 0; i < LinkedList.MAX_ITEMS; i++) { + bytes32 id = _buildItemId(list.nonce); + _addItemToList(list, id, i); + } + + vm.expectRevert(LinkedList.LinkedListMaxElementsExceeded.selector); + list.add(_buildItemId(list.nonce)); + } + + function test_Remove_RevertGiven_TheListIsEmpty() external { + vm.expectRevert(LinkedList.LinkedListEmptyList.selector); + list.remove(_getNextItem, _deleteItem); + } + + function test_Remove_GivenTheListIsNotEmpty() external { + _assert_addItem(_buildItemId(list.nonce), 0); + _assert_removeItem(); + } + + function test_TraverseGivenTheListIsEmpty() external { + _assert_traverseList(_processItemAddition, abi.encode(0), 0, abi.encode(0)); + } + + modifier givenTheListIsNotEmpty() { + for (uint256 i = 0; i < LIST_LENGTH; i++) { + bytes32 id = _buildItemId(list.nonce); + _assert_addItem(id, i); + } + _; + } + + function test_TraverseWhenIterationsAreNotSpecified() external givenTheListIsNotEmpty { + // calculate sum of all item idexes - it's what _processItemAddition does + uint256 sum = 0; + for (uint256 i = 0; i < list.count; i++) { + sum += i; + } + _assert_traverseList(_processItemAddition, abi.encode(0), 0, abi.encode(sum)); + } + + function test_TraverseWhenIterationsAreSpecified(uint256 n) external givenTheListIsNotEmpty { + vm.assume(n > 0); + vm.assume(n < LIST_LENGTH); + uint256 sum = 0; + for (uint256 i = 0; i < n; i++) { + sum += i; + } + _assert_traverseList(_processItemAddition, abi.encode(0), n, abi.encode(sum)); + } + + function test_TraverseWhenIterationsAreInvalid() external givenTheListIsNotEmpty { + uint256 n = LIST_LENGTH + 1; + uint256 sum = 0; + for (uint256 i = 0; i < n; i++) { + sum += i; + } + vm.expectRevert(LinkedList.LinkedListInvalidIterations.selector); + _assert_traverseList(_processItemAddition, abi.encode(0), n, abi.encode(sum)); + } + + // -- Assertions -- + function _assert_addItem(bytes32 id, uint256 idIndex) internal { + uint256 beforeNonce = list.nonce; + uint256 beforeCount = list.count; + bytes32 beforeHead = list.head; + + ids[idIndex] = _addItemToList(list, id, idIndex); + + uint256 afterNonce = list.nonce; + uint256 afterCount = list.count; + bytes32 afterTail = list.tail; + bytes32 afterHead = list.head; + + assertEq(afterNonce, beforeNonce + 1); + assertEq(afterCount, beforeCount + 1); + + if (beforeCount == 0) { + assertEq(afterHead, id); + } else { + assertEq(afterHead, beforeHead); + } + assertEq(afterTail, id); + } + + function _assert_removeItem() internal { + uint256 beforeNonce = list.nonce; + uint256 beforeCount = list.count; + bytes32 beforeTail = list.tail; + bytes32 beforeHead = list.head; + + Item memory beforeHeadItem = items[beforeHead]; + + list.remove(_getNextItem, _deleteItem); + + uint256 afterNonce = list.nonce; + uint256 afterCount = list.count; + bytes32 afterTail = list.tail; + bytes32 afterHead = list.head; + + assertEq(afterNonce, beforeNonce); + assertEq(afterCount, beforeCount - 1); + + if (afterCount == 0) { + assertEq(afterTail, bytes32(0)); + } else { + assertEq(afterTail, beforeTail); + } + assertEq(afterHead, beforeHeadItem.next); + } + + function _assert_traverseList( + function(bytes32, bytes memory) internal returns (bool, bytes memory) _processItem, + bytes memory _initAcc, + uint256 _n, + bytes memory _expectedAcc + ) internal { + uint256 beforeNonce = list.nonce; + uint256 beforeCount = list.count; + bytes32 beforeTail = list.tail; + bytes32 beforeHead = list.head; + + // calculate after head item + bytes32 calcAfterHead = beforeHead; + if (_n != 0) { + for (uint256 i = 0; i < _n; i++) { + calcAfterHead = _getNextItem(calcAfterHead); + } + } + + (uint256 processedCount, bytes memory acc) = + list.traverse(_getNextItem, _processItem, _deleteItem, _initAcc, _n); + uint256 afterNonce = list.nonce; + uint256 afterCount = list.count; + bytes32 afterTail = list.tail; + bytes32 afterHead = list.head; + + assertEq(processedCount, _n == 0 ? beforeCount : _n); + assertEq(acc, _expectedAcc); + + assertEq(afterNonce, beforeNonce); + assertEq(afterCount, _n == 0 ? 0 : beforeCount - _n); + + if (_n == 0) { + assertEq(afterTail, bytes32(0)); + assertEq(afterHead, bytes32(0)); + } else { + assertEq(afterTail, beforeTail); + assertEq(afterHead, calcAfterHead); + } + } +} diff --git a/packages/horizon/test/libraries/LinkedList.tree b/packages/horizon/test/libraries/LinkedList.tree new file mode 100644 index 000000000..dc5143cb4 --- /dev/null +++ b/packages/horizon/test/libraries/LinkedList.tree @@ -0,0 +1,34 @@ +LinkedListTest::add_ +├── given the list is empty +│ ├── it should have a count of 1 and nonce of 1 +│ ├── it should have the tail set to the element +│ └── it should have the head set to the element +├── given the list is not empty +│ ├── it should have a count of 2 and nonce of 2 +│ ├── it should have the tail set to the new element +│ └── it should have the head set to the old element +└── given the list is at max size + └── it should revert + +LinkedListTest::remove_ +├── given the list is empty +│ └── it should revert +└── given the list is not empty + ├── it should have a count of 0 + ├── it should have the tail set to bytes32(0) + └── it should have the head set to bytes32(0) + +LinkedListTest::traverse +├── given the list is empty +│ ├── it should return zero processed elements +│ └── it should return accumulator value same as the initial value +└── given the list is not empty + └── when iterations are not specified + │ ├── it should return process all elements + │ └── it should return accumulator value equal to the processed value + └── when iterations are specified + │ ├── it should return process all elements + │ └── it should return accumulator value equal to the processed value + └── when iterations are invalid + ├── it should return process all elements + └── it should return accumulator value equal to the processed value diff --git a/packages/horizon/test/libraries/ListImplementation.sol b/packages/horizon/test/libraries/ListImplementation.sol new file mode 100644 index 000000000..0ec024435 --- /dev/null +++ b/packages/horizon/test/libraries/ListImplementation.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import { LinkedList } from "../../contracts/libraries/LinkedList.sol"; + +contract ListImplementation { + using LinkedList for LinkedList.List; + + uint256 constant LIST_LENGTH = 100; + + struct Item { + uint256 data; + bytes32 next; + } + + LinkedList.List public list; + mapping(bytes32 id => Item data) public items; + bytes32[LIST_LENGTH] public ids; + + function _addItemToList(LinkedList.List storage _list, bytes32 _id, uint256 _data) internal returns (bytes32) { + items[_id] = Item({ data: _data, next: bytes32(0) }); + if (_list.count != 0) { + items[_list.tail].next = _id; + } + _list.add(_id); + return _id; + } + + function _deleteItem(bytes32 _id) internal { + delete items[_id]; + } + + function _getNextItem(bytes32 _id) internal view returns (bytes32) { + return items[_id].next; + } + + function _processItemAddition(bytes32 _id, bytes memory _acc) internal returns (bool, bytes memory) { + uint256 sum = abi.decode(_acc, (uint256)); + sum += items[_id].data; + return (false, abi.encode(sum)); // dont break, do delete + } + + function _buildItemId(uint256 nonce) internal view returns (bytes32) { + // use block.number to salt the id generation to avoid + // accidentally using dirty state on repeat tests + return bytes32(keccak256(abi.encode(nonce, block.number))); + } +} diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index e74db32ce..e6ecc555c 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -43,7 +43,7 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { vm.assume(amount > 0); _createThawRequest(amount); skip(thawingPeriod + 1); - _deprovision(amount); + _deprovision(0); _; } From c8c4eeb8ce0f5167c46b92b5a9b24ae891e6da81 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 16:13:36 -0300 Subject: [PATCH 107/277] chore: added more staking service provider tests --- .../serviceProvider/serviceProvider.t.sol | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol index 9a1885e87..5461698e3 100644 --- a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol +++ b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol @@ -102,6 +102,38 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { uint256 delegationAmount ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { uint256 providerTokensAvailable = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + // Should not include delegated tokens assertEq(providerTokensAvailable, amount); } + + function testServiceProvider_HasStake( + uint256 amount + ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) { + assertTrue(staking.hasStake(users.indexer)); + + _createThawRequest(amount); + skip(MAX_THAWING_PERIOD + 1); + _deprovision(0); + staking.unstake(amount); + + assertFalse(staking.hasStake(users.indexer)); + } + + function testServiceProvider_GetIndexerStakedTokens( + uint256 amount + ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) { + assertEq(staking.getIndexerStakedTokens(users.indexer), amount); + + _createThawRequest(amount); + // Does not discount thawing tokens + assertEq(staking.getIndexerStakedTokens(users.indexer), amount); + + skip(MAX_THAWING_PERIOD + 1); + _deprovision(0); + // Does not discount thawing tokens + assertEq(staking.getIndexerStakedTokens(users.indexer), amount); + + staking.unstake(amount); + assertEq(staking.getIndexerStakedTokens(users.indexer), 0); + } } \ No newline at end of file From 05de8aa8826e747fe3df504d93a5f7079ec25954 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 4 Jun 2024 19:05:36 -0300 Subject: [PATCH 108/277] fix: remove MIN_PROVISION_SIZE from horizon staking --- .../contracts/staking/HorizonStaking.sol | 5 +-- .../HorizonStakingShared.t.sol | 4 +-- .../horizon/test/staking/HorizonStaking.t.sol | 4 +-- .../test/staking/allocation/allocation.t.sol | 0 .../test/staking/delegation/delegate.t.sol | 2 +- .../test/staking/delegation/undelegate.t.sol | 4 +-- .../test/staking/provision/deprovision.t.sol | 18 +++-------- .../test/staking/provision/provision.t.sol | 14 ++------- .../test/staking/provision/reprovision.t.sol | 12 +++---- .../horizon/test/staking/slash/slash.t.sol | 31 ++++++++++++++++--- packages/horizon/test/staking/thaw/thaw.t.sol | 2 ++ packages/horizon/test/utils/Constants.sol | 3 +- 12 files changed, 51 insertions(+), 48 deletions(-) create mode 100644 packages/horizon/test/staking/allocation/allocation.t.sol diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index c8d7f437f..4caa10a96 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -34,9 +34,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /// It is equivalent to 100% in parts-per-million uint32 private constant MAX_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); - /// @dev Minimum size of a provision - uint256 private constant MIN_PROVISION_SIZE = 1e18; - /// @dev Fixed point precision uint256 private constant FIXED_POINT_PRECISION = 1e18; @@ -599,7 +596,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 _maxVerifierCut, uint64 _thawingPeriod ) private { - require(_tokens >= MIN_PROVISION_SIZE, HorizonStakingInsufficientTokens(_tokens, MIN_PROVISION_SIZE)); + require(_tokens > 0, HorizonStakingInvalidZeroTokens()); require( _maxVerifierCut <= MAX_MAX_VERIFIER_CUT, HorizonStakingInvalidMaxVerifierCut(_maxVerifierCut, MAX_MAX_VERIFIER_CUT) diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 85cbbcbaf..1f1ea3310 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -19,14 +19,14 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { } modifier assumeProvisionTokens(uint256 tokens) { - vm.assume(tokens > MIN_PROVISION_SIZE); + vm.assume(tokens > 0); vm.assume(tokens <= MAX_STAKING_TOKENS); _; } modifier useProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) { vm.assume(tokens <= MAX_STAKING_TOKENS); - vm.assume(tokens > MIN_PROVISION_SIZE); + vm.assume(tokens > 0); vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); _createProvision(subgraphDataServiceAddress, tokens, maxVerifierCut, thawingPeriod); diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index e6ecc555c..bb3703b34 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -21,14 +21,14 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { } modifier useStake(uint256 amount) { - vm.assume(amount > MIN_PROVISION_SIZE); + vm.assume(amount > 0); approve(address(staking), amount); staking.stake(amount); _; } modifier useStakeTo(address to, uint256 amount) { - vm.assume(amount > MIN_PROVISION_SIZE); + vm.assume(amount > 0); _stakeTo(to, amount); _; } diff --git a/packages/horizon/test/staking/allocation/allocation.t.sol b/packages/horizon/test/staking/allocation/allocation.t.sol new file mode 100644 index 000000000..e69de29bb diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 708c3bf5c..c254756fc 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -48,7 +48,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount ) public useIndexer { - amount = bound(amount, MIN_PROVISION_SIZE, MAX_STAKING_TOKENS); + amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 9b74f729d..5dcc85183 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -44,7 +44,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); - overDelegationShares = bound(overDelegationShares, delegation.shares + 1, MAX_STAKING_TOKENS); + overDelegationShares = bound(overDelegationShares, delegation.shares + 1, MAX_STAKING_TOKENS + 1); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientShares(uint256,uint256)", @@ -80,7 +80,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount ) public useIndexer { - amount = bound(amount, MIN_PROVISION_SIZE, MAX_STAKING_TOKENS); + amount = bound(amount, 1, MAX_STAKING_TOKENS); delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index 9f3438739..fbb9d0fc4 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -30,24 +30,16 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { uint64 thawingPeriod, uint256 thawAmount ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - thawAmount = bound(thawAmount, MIN_DELEGATION, amount); + vm.assume(amount > 1); + thawAmount = bound(thawAmount, 2, amount); uint256 thawAmount1 = thawAmount / 2; - bytes32 thawRequestId = _createThawRequest(thawAmount1); - bytes32 thawRequestId2 = _createThawRequest(thawAmount - thawAmount1); - skip(thawingPeriod + 1); - - console.log("thawAmount1: ", thawAmount1); - console.log("thawAmount2: ", thawAmount - thawAmount1); + _createThawRequest(thawAmount1); + _createThawRequest(thawAmount - thawAmount1); - ThawRequest memory thawRequest1 = staking.getThawRequest(thawRequestId); - ThawRequest memory thawRequest2 = staking.getThawRequest(thawRequestId2); - console.log("Thaw request 1 shares: ", thawRequest1.shares); - console.log("Thaw request 2 shares: ", thawRequest2.shares); + skip(thawingPeriod + 1); - console.log("Idle stake before deprovision: ", staking.getIdleStake(users.indexer)); _deprovision(1); uint256 idleStake = staking.getIdleStake(users.indexer); - console.log("Idle stake after deprovision: ", idleStake); assertEq(idleStake, thawAmount1); } diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index 823a87d54..fc941ec7f 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -20,22 +20,16 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { assertEq(provisionTokens, amount); } - function testProvision_RevertWhen_InsufficientTokens(uint256 amount) public useIndexer useStake(1000 ether) { - amount = bound(amount, 0, MIN_PROVISION_SIZE - 1); - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokens(uint256,uint256)", - amount, - MIN_PROVISION_SIZE - ); + function testProvision_RevertWhen_ZeroTokens() public useIndexer useStake(1000 ether) { + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); vm.expectRevert(expectedError); - staking.provision(users.indexer, subgraphDataServiceAddress, amount, 0, 0); + staking.provision(users.indexer, subgraphDataServiceAddress, 0, 0, 0); } function testProvision_RevertWhen_MaxVerifierCutTooHigh( uint256 amount, uint32 maxVerifierCut ) public useIndexer useStake(amount) { - vm.assume(amount > MIN_PROVISION_SIZE); vm.assume(maxVerifierCut > MAX_MAX_VERIFIER_CUT); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInvalidMaxVerifierCut(uint32,uint32)", @@ -50,7 +44,6 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { uint256 amount, uint64 thawingPeriod ) public useIndexer useStake(amount) { - vm.assume(amount > MIN_PROVISION_SIZE); vm.assume(thawingPeriod > MAX_THAWING_PERIOD); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInvalidThawingPeriod(uint64,uint64)", @@ -65,7 +58,6 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { uint256 amount, uint256 provisionTokens ) public useIndexer useStake(amount) { - vm.assume(amount > MIN_PROVISION_SIZE); vm.assume(provisionTokens > amount); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientIdleStake(uint256,uint256)", diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 3d1d803dc..5d7ed8068 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -36,7 +36,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { { skip(thawingPeriod + 1); - _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); + _createProvision(newDataService, 1 ether, 0, thawingPeriod); // nThawRequests == 0 reprovisions all thaw requests _reprovision(provisionAmount, 0); @@ -44,7 +44,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { assertEq(idleStake, 0 ether); uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, newDataService); - assertEq(provisionTokens, provisionAmount + MIN_PROVISION_SIZE); + assertEq(provisionTokens, provisionAmount + 1 ether); } function testReprovision_OperatorMovingTokens( @@ -64,13 +64,13 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { // Switch back to operator vm.startPrank(users.operator); - _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); + _createProvision(newDataService, 1 ether, 0, thawingPeriod); _reprovision(provisionAmount, 0); uint256 idleStake = staking.getIdleStake(users.indexer); assertEq(idleStake, 0 ether); uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, newDataService); - assertEq(provisionTokens, provisionAmount + MIN_PROVISION_SIZE); + assertEq(provisionTokens, provisionAmount + 1 ether); } function testReprovision_RevertWhen_OperatorNotAuthorizedForNewDataService( @@ -83,7 +83,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { { // Switch to indexer to create new provision vm.startPrank(users.indexer); - _createProvision(newDataService, MIN_PROVISION_SIZE, 0, 0); + _createProvision(newDataService, 1 ether, 0, 0); // Switch back to operator vm.startPrank(users.operator); @@ -116,7 +116,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { { vm.assume(thawingPeriod > 0); - _createProvision(newDataService, MIN_PROVISION_SIZE, 0, thawingPeriod); + _createProvision(newDataService, 1 ether, 0, thawingPeriod); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientIdleStake(uint256,uint256)", diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 50f4d1e88..758ebc1cf 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -39,9 +39,9 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 verifierCutAmount ) public useIndexer useProvision(amount, maxVerifierCut, 0) { verifierCutAmount = bound(verifierCutAmount, 0, maxVerifierCut); - - // TODO: when slashing for low amounts there's an arithmetic underflow - slashAmount = bound(slashAmount, MIN_PROVISION_SIZE, amount); + slashAmount = bound(slashAmount, 1, amount); + uint256 maxVerifierTokens = (slashAmount * maxVerifierCut) / MAX_PPM; + vm.assume(verifierCutAmount <= maxVerifierTokens); vm.startPrank(subgraphDataServiceAddress); _slash(slashAmount, verifierCutAmount); @@ -53,6 +53,24 @@ contract HorizonStakingSlashTest is HorizonStakingTest { assertEq(verifierTokens, verifierCutAmount); } + function testSlash_RevertWhen_TooManyTokens( + uint256 amount, + uint32 maxVerifierCut, + uint256 verifierCutAmount + ) public useIndexer useProvision(amount, maxVerifierCut, 0) { + uint256 maxVerifierTokens = (amount * maxVerifierCut) / MAX_PPM; + verifierCutAmount = bound(verifierCutAmount, maxVerifierTokens + 1, MAX_STAKING_TOKENS); + + vm.startPrank(subgraphDataServiceAddress); + bytes memory expectedError = abi.encodeWithSignature( + "HorizonStakingTooManyTokens(uint256,uint256)", + verifierCutAmount, + maxVerifierTokens + ); + vm.expectRevert(expectedError); + _slash(amount, verifierCutAmount); + } + function testSlash_DelegationDisabled_SlashingOverProvisionTokens( uint256 amount, uint256 slashAmount, @@ -62,6 +80,8 @@ contract HorizonStakingSlashTest is HorizonStakingTest { delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); + uint256 maxVerifierTokens = (amount * MAX_MAX_VERIFIER_CUT) / MAX_PPM; + vm.assume(verifierCutAmount <= maxVerifierTokens); resetPrank(users.delegator); _delegate(delegationAmount, subgraphDataServiceAddress); @@ -89,6 +109,8 @@ contract HorizonStakingSlashTest is HorizonStakingTest { delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); + uint256 maxVerifierTokens = (amount * MAX_MAX_VERIFIER_CUT) / MAX_PPM; + vm.assume(verifierCutAmount <= maxVerifierTokens); resetPrank(users.delegator); _delegate(delegationAmount, subgraphDataServiceAddress); @@ -111,8 +133,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 amount, uint256 slashAmount ) public useIndexer useStake(amount) { - // TODO: when slashing for low amounts there's an arithmetic underflow - slashAmount = bound(slashAmount, MIN_PROVISION_SIZE, amount); + slashAmount = bound(slashAmount, 1, amount); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientTokens(uint256,uint256)", 0 ether, diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/thaw/thaw.t.sol index 1f747f7f0..2ed99682f 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/thaw/thaw.t.sol @@ -35,6 +35,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { uint256 thawAmount, uint256 thawAmount2 ) public useIndexer useProvision(amount, 0, thawingPeriod) { + vm.assume(amount > 1); thawAmount = bound(thawAmount, 1, amount - 1); thawAmount2 = bound(thawAmount2, 1, amount - thawAmount); bytes32 thawRequestId = _createThawRequest(thawAmount); @@ -96,6 +97,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { uint64 thawingPeriod, uint256 thawAmount ) public useIndexer useProvision(amount, 0, thawingPeriod) { + vm.assume(amount >= MAX_THAW_REQUESTS + 1); thawAmount = bound(thawAmount, 1, amount / (MAX_THAW_REQUESTS + 1)); for (uint256 i = 0; i < 100; i++) { diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index 46445b039..f3e7f1157 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -12,8 +12,7 @@ abstract contract Constants { uint256 internal constant protocolPaymentCut = 10000; // Staking constants uint256 internal constant MAX_THAW_REQUESTS = 100; - uint256 internal constant MIN_PROVISION_SIZE = 1e18; uint32 internal constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% in parts per million uint64 internal constant MAX_THAWING_PERIOD = 28 days; - uint256 internal constant MIN_DELEGATION = 1e18; + uint256 internal constant MIN_DELEGATION = 1 ether; } \ No newline at end of file From 3a4507c2f90366e924bd975d368111a3f8dd607a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 5 Jun 2024 11:49:15 -0300 Subject: [PATCH 109/277] test: add provision tracker tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../libraries/ProvisionTracker.t.sol | 110 ++++++++++++++++++ .../libraries/ProvisionTracker.tree | 11 ++ .../ProvisionTrackerImplementation.sol | 8 ++ .../HorizonStakingShared.t.sol | 2 +- 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol create mode 100644 packages/horizon/test/data-service/libraries/ProvisionTracker.tree create mode 100644 packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol diff --git a/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol b/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol new file mode 100644 index 000000000..6155bf4c7 --- /dev/null +++ b/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; +import { ProvisionTrackerImplementation } from "./ProvisionTrackerImplementation.sol"; +import { ProvisionTracker } from "../../../contracts/data-service/libraries/ProvisionTracker.sol"; +import { IHorizonStaking } from "./../../../contracts/interfaces/IHorizonStaking.sol"; + +// Wrapper required because when using vm.expectRevert, the error is expected in the next immediate call +// Which in the case of this library is an internal call to the staking contract +// See: https://github.com/foundry-rs/foundry/issues/5454 +library ProvisionTrackerWrapper { + function lock( + mapping(address => uint256) storage self, + IHorizonStaking graphStaking, + address serviceProvider, + uint256 tokens, + uint32 delegationRatio + ) external { + ProvisionTracker.lock(self, graphStaking, serviceProvider, tokens, delegationRatio); + } + + function release(mapping(address => uint256) storage self, address serviceProvider, uint256 tokens) external { + ProvisionTracker.release(self, serviceProvider, tokens); + } +} + +contract ProvisionTrackerTest is HorizonStakingSharedTest, ProvisionTrackerImplementation { + using ProvisionTrackerWrapper for mapping(address => uint256); + + modifier useProvision( + uint256 tokens, + uint32, + uint64 + ) override { + vm.assume(tokens > 0); + vm.assume(tokens <= MAX_STAKING_TOKENS); + _createProvision(address(this), tokens, 0, 0); + _; + } + + function test_Lock_GivenTheProvisionHasSufficientAvailableTokens( + uint256 tokens, + uint256 steps + ) external useIndexer useProvision(tokens, 0, 0) { + vm.assume(tokens > 0); + vm.assume(steps > 0); + vm.assume(steps < 100); + uint256 stepAmount = tokens / steps; + + for (uint256 i = 0; i < steps; i++) { + uint256 beforeLockedAmount = provisionTracker[users.indexer]; + provisionTracker.lock(staking, users.indexer, stepAmount, uint32(0)); + uint256 afterLockedAmount = provisionTracker[users.indexer]; + assertEq(afterLockedAmount, beforeLockedAmount + stepAmount); + } + + assertEq(provisionTracker[users.indexer], stepAmount * steps); + uint256 delta = (tokens % steps); + uint256 tokensAvailable = staking.getTokensAvailable(users.indexer, address(this), 0); + assertEq(tokensAvailable - provisionTracker[users.indexer], delta); + } + + function test_Lock_RevertGiven_TheProvisionHasInsufficientAvailableTokens( + uint256 tokens + ) external useIndexer useProvision(tokens, 0, 0) { + uint256 tokensToLock = tokens + 1; + vm.expectRevert( + abi.encodeWithSelector(ProvisionTracker.ProvisionTrackerInsufficientTokens.selector, tokens, tokensToLock) + ); + provisionTracker.lock(staking, users.indexer, tokensToLock, uint32(0)); + } + + function test_Release_GivenTheProvisionHasSufficientLockedTokens( + uint256 tokens, + uint256 steps + ) external useIndexer useProvision(tokens, 0, 0) { + vm.assume(tokens > 0); + vm.assume(steps > 0); + vm.assume(steps < 100); + + // setup + provisionTracker.lock(staking, users.indexer, tokens, uint32(0)); + + // lock entire provision, then unlock in steps + uint256 stepAmount = tokens / steps; + + for (uint256 i = 0; i < steps; i++) { + uint256 beforeLockedAmount = provisionTracker[users.indexer]; + provisionTracker.release(users.indexer, stepAmount); + uint256 afterLockedAmount = provisionTracker[users.indexer]; + assertEq(afterLockedAmount, beforeLockedAmount - stepAmount); + } + + assertEq(provisionTracker[users.indexer], tokens - stepAmount * steps); + uint256 delta = (tokens % steps); + assertEq(provisionTracker[users.indexer], delta); + } + + function test_Release_RevertGiven_TheProvisionHasInsufficientLockedTokens(uint256 tokens) external useIndexer useProvision(tokens, 0, 0) { + // setup + provisionTracker.lock(staking, users.indexer, tokens, uint32(0)); + + uint256 tokensToRelease = tokens + 1; + vm.expectRevert( + abi.encodeWithSelector(ProvisionTracker.ProvisionTrackerInsufficientTokens.selector, tokens, tokensToRelease) + ); + provisionTracker.release(users.indexer, tokensToRelease); + } +} diff --git a/packages/horizon/test/data-service/libraries/ProvisionTracker.tree b/packages/horizon/test/data-service/libraries/ProvisionTracker.tree new file mode 100644 index 000000000..34955ed76 --- /dev/null +++ b/packages/horizon/test/data-service/libraries/ProvisionTracker.tree @@ -0,0 +1,11 @@ +ProvisionTrackerTest::lock_ +├── given the provision has sufficient available tokens +│ └── it should lock the tokens +└── given the provision has insufficient available tokens + └── it should revert + +ProvisionTrackerTest::release_ +├── given the provision has sufficient locked tokens +│ └── it should release the tokens +└── given the provision has insufficient locked tokens + └── it should revert \ No newline at end of file diff --git a/packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol b/packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol new file mode 100644 index 000000000..0093fba72 --- /dev/null +++ b/packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import { ProvisionTracker } from "../../../contracts/data-service/libraries/ProvisionTracker.sol"; + +contract ProvisionTrackerImplementation { + mapping(address => uint256) public provisionTracker; +} diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 1f1ea3310..8ab125dcb 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -24,7 +24,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { _; } - modifier useProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) { + modifier useProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) virtual { vm.assume(tokens <= MAX_STAKING_TOKENS); vm.assume(tokens > 0); vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); From 783c6f78a8b7fed66631592a2c528a8cc6c2e4ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 5 Jun 2024 16:22:52 -0300 Subject: [PATCH 110/277] test: add GraphDirectory tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 2 +- .../utilities/ProvisionManager.sol | 2 +- .../contracts/payments/GraphPayments.sol | 2 +- .../contracts/payments/PaymentsEscrow.sol | 2 +- .../payments/collectors/TAPCollector.sol | 2 +- .../contracts/staking/utilities/Managed.sol | 2 +- .../GraphDirectory.sol | 44 +++++------ .../test/deployments/Deployments.t.sol | 29 -------- .../test/utilities/GraphDirectory.t.sol | 73 +++++++++++++++++++ .../test/utilities/GraphDirectory.tree | 11 +++ .../GraphDirectoryImplementation.sol | 69 ++++++++++++++++++ 11 files changed, 181 insertions(+), 57 deletions(-) rename packages/horizon/contracts/{data-service => utilities}/GraphDirectory.sol (90%) delete mode 100644 packages/horizon/test/deployments/Deployments.t.sol create mode 100644 packages/horizon/test/utilities/GraphDirectory.t.sol create mode 100644 packages/horizon/test/utilities/GraphDirectory.tree create mode 100644 packages/horizon/test/utilities/GraphDirectoryImplementation.sol diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index f986224b3..db0a2bd11 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { IDataService } from "./interfaces/IDataService.sol"; import { DataServiceV1Storage } from "./DataServiceStorage.sol"; -import { GraphDirectory } from "./GraphDirectory.sol"; +import { GraphDirectory } from "../utilities/GraphDirectory.sol"; import { ProvisionManager } from "./utilities/ProvisionManager.sol"; /** diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 24230997e..247567bc2 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -6,7 +6,7 @@ import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; import { UintRange } from "../../libraries/UintRange.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { GraphDirectory } from "../GraphDirectory.sol"; +import { GraphDirectory } from "../../utilities/GraphDirectory.sol"; import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; /** diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index a3e1b2dd7..298a1a74c 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -9,7 +9,7 @@ import { MulticallUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { PPMMath } from "../libraries/PPMMath.sol"; -import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +import { GraphDirectory } from "../utilities/GraphDirectory.sol"; /** * @title GraphPayments contract diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 8b9e8c768..6f5ee9282 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -8,7 +8,7 @@ import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; -import { GraphDirectory } from "../data-service/GraphDirectory.sol"; +import { GraphDirectory } from "../utilities/GraphDirectory.sol"; /** * @title PaymentsEscrow contract diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index a80e08cdf..77e086022 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -7,7 +7,7 @@ import { ITAPCollector } from "../../interfaces/ITAPCollector.sol"; import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import { PPMMath } from "../../libraries/PPMMath.sol"; -import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; +import { GraphDirectory } from "../../utilities/GraphDirectory.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index 5f5a0f6b3..4d8e77b4f 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; -import { GraphDirectory } from "../../data-service/GraphDirectory.sol"; +import { GraphDirectory } from "../../utilities/GraphDirectory.sol"; // TODO: create custom var-name-mixedcase /* solhint-disable var-name-mixedcase */ diff --git a/packages/horizon/contracts/data-service/GraphDirectory.sol b/packages/horizon/contracts/utilities/GraphDirectory.sol similarity index 90% rename from packages/horizon/contracts/data-service/GraphDirectory.sol rename to packages/horizon/contracts/utilities/GraphDirectory.sol index 085ee8a8b..570a5d476 100644 --- a/packages/horizon/contracts/data-service/GraphDirectory.sol +++ b/packages/horizon/contracts/utilities/GraphDirectory.sol @@ -78,17 +78,17 @@ abstract contract GraphDirectory { * @param graphCuration The Curation contract address */ event GraphDirectoryInitialized( - IGraphToken indexed graphToken, - IHorizonStaking indexed graphStaking, - IGraphPayments graphPayments, - IPaymentsEscrow graphEscrow, - IController indexed graphController, - IEpochManager graphEpochManager, - IRewardsManager graphRewardsManager, - ITokenGateway graphTokenGateway, - IBridgeEscrow graphBridgeEscrow, - IGraphProxyAdmin graphProxyAdmin, - ICuration graphCuration + address indexed graphToken, + address indexed graphStaking, + address graphPayments, + address graphEscrow, + address indexed graphController, + address graphEpochManager, + address graphRewardsManager, + address graphTokenGateway, + address graphBridgeEscrow, + address graphProxyAdmin, + address graphCuration ); /** @@ -123,17 +123,17 @@ abstract contract GraphDirectory { GRAPH_CURATION = ICuration(_getContractFromController("Curation")); emit GraphDirectoryInitialized( - GRAPH_TOKEN, - GRAPH_STAKING, - GRAPH_PAYMENTS, - GRAPH_PAYMENTS_ESCROW, - GRAPH_CONTROLLER, - GRAPH_EPOCH_MANAGER, - GRAPH_REWARDS_MANAGER, - GRAPH_TOKEN_GATEWAY, - GRAPH_BRIDGE_ESCROW, - GRAPH_PROXY_ADMIN, - GRAPH_CURATION + address(GRAPH_TOKEN), + address(GRAPH_STAKING), + address(GRAPH_PAYMENTS), + address(GRAPH_PAYMENTS_ESCROW), + address(GRAPH_CONTROLLER), + address(GRAPH_EPOCH_MANAGER), + address(GRAPH_REWARDS_MANAGER), + address(GRAPH_TOKEN_GATEWAY), + address(GRAPH_BRIDGE_ESCROW), + address(GRAPH_PROXY_ADMIN), + address(GRAPH_CURATION) ); } diff --git a/packages/horizon/test/deployments/Deployments.t.sol b/packages/horizon/test/deployments/Deployments.t.sol deleted file mode 100644 index f3c088ab7..000000000 --- a/packages/horizon/test/deployments/Deployments.t.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { GraphBaseTest } from "../GraphBase.t.sol"; - -contract GraphDeploymentsTest is GraphBaseTest { - - /* - * HELPERS - */ - - function _getContractFromController(bytes memory _contractName) private view returns (address) { - return controller.getContractProxy(keccak256(_contractName)); - } - - /* - * TESTS - */ - - function testDeployments() public view { - assertEq(_getContractFromController("GraphPayments"), address(payments)); - assertEq(_getContractFromController("GraphToken"), address(token)); - assertEq(_getContractFromController("Staking"), address(staking)); - assertEq(_getContractFromController("PaymentsEscrow"), address(escrow)); - assertEq(_getContractFromController("GraphProxyAdmin"), address(proxyAdmin)); - } -} diff --git a/packages/horizon/test/utilities/GraphDirectory.t.sol b/packages/horizon/test/utilities/GraphDirectory.t.sol new file mode 100644 index 000000000..6a2c958b8 --- /dev/null +++ b/packages/horizon/test/utilities/GraphDirectory.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; +import { stdStorage, StdStorage } from "forge-std/Test.sol"; +import { GraphBaseTest } from "../GraphBase.t.sol"; +import { GraphDirectory } from "./../../contracts/utilities/GraphDirectory.sol"; +import { GraphDirectoryImplementation } from "./GraphDirectoryImplementation.sol"; + +contract GraphDirectoryTest is GraphBaseTest { + function test_WhenTheContractIsDeployedWithAValidController() external { + vm.expectEmit(); + emit GraphDirectory.GraphDirectoryInitialized( + _getContractFromController("GraphToken"), + _getContractFromController("Staking"), + _getContractFromController("GraphPayments"), + _getContractFromController("PaymentsEscrow"), + address(controller), + _getContractFromController("EpochManager"), + _getContractFromController("RewardsManager"), + _getContractFromController("GraphTokenGateway"), + _getContractFromController("BridgeEscrow"), + _getContractFromController("GraphProxyAdmin"), + _getContractFromController("Curation") + ); + _deployImplementation(address(controller)); + } + + function test_RevertWhen_TheContractIsDeployedWithAnInvalidController(address controller_) external { + vm.assume(controller_ != address(controller)); + vm.assume(controller_ != address(0)); + + vm.expectRevert(); // call to getContractProxy on a random address reverts + _deployImplementation(controller_); + } + + function test_RevertWhen_TheContractIsDeployedWithTheZeroAddressAsTheInvalidController() external { + vm.expectRevert(abi.encodeWithSelector(GraphDirectory.GraphDirectoryInvalidZeroAddress.selector, "Controller")); // call to getContractProxy on a random address reverts + _deployImplementation(address(0)); + } + + function test_WhenTheContractGettersAreCalled() external { + GraphDirectoryImplementation directory = _deployImplementation(address(controller)); + + assertEq(_getContractFromController("GraphToken"), address(directory.graphToken())); + assertEq(_getContractFromController("Staking"), address(directory.graphStaking())); + assertEq(_getContractFromController("GraphPayments"), address(directory.graphPayments())); + assertEq(_getContractFromController("PaymentsEscrow"), address(directory.graphPaymentsEscrow())); + assertEq(_getContractFromController("EpochManager"), address(directory.graphEpochManager())); + assertEq(_getContractFromController("RewardsManager"), address(directory.graphRewardsManager())); + assertEq(_getContractFromController("GraphTokenGateway"), address(directory.graphTokenGateway())); + assertEq(_getContractFromController("BridgeEscrow"), address(directory.graphBridgeEscrow())); + assertEq(_getContractFromController("GraphProxyAdmin"), address(directory.graphProxyAdmin())); + assertEq(_getContractFromController("Curation"), address(directory.graphCuration())); + } + + function test_RevertWhen_AnInvalidContractGetterIsCalled() external { + // Zero out the Staking contract address to simulate a non registered contract + bytes32 storageSlot = keccak256(abi.encode(keccak256("Staking"), 5)); + vm.store(address(controller), storageSlot, bytes32(0)); + + vm.expectRevert(abi.encodeWithSelector(GraphDirectory.GraphDirectoryInvalidZeroAddress.selector, "Staking")); + _deployImplementation(address(controller)); + } + + function _deployImplementation(address _controller) private returns (GraphDirectoryImplementation) { + return new GraphDirectoryImplementation(_controller); + } + + function _getContractFromController(bytes memory _contractName) private view returns (address) { + return controller.getContractProxy(keccak256(_contractName)); + } +} diff --git a/packages/horizon/test/utilities/GraphDirectory.tree b/packages/horizon/test/utilities/GraphDirectory.tree new file mode 100644 index 000000000..fc928ec29 --- /dev/null +++ b/packages/horizon/test/utilities/GraphDirectory.tree @@ -0,0 +1,11 @@ +GraphDirectoryTest +├── when the contract is deployed with a valid controller +│ └── it should emit an initialization event +├── when the contract is deployed with an invalid controller +│ └── it should revert +├── when the contract is deployed with the zero address as the invalid controller +│ └── it should revert +├── when the contract getters are called +│ └── it should return the contract address +└── when an invalid contract getter is called + └── it should revert \ No newline at end of file diff --git a/packages/horizon/test/utilities/GraphDirectoryImplementation.sol b/packages/horizon/test/utilities/GraphDirectoryImplementation.sol new file mode 100644 index 000000000..9f4b5066c --- /dev/null +++ b/packages/horizon/test/utilities/GraphDirectoryImplementation.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.26; + +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IHorizonStaking } from "../../contracts/interfaces/IHorizonStaking.sol"; +import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; +import { IPaymentsEscrow } from "../../contracts/interfaces/IPaymentsEscrow.sol"; + +import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; +import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; +import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; +import { ITokenGateway } from "@graphprotocol/contracts/contracts/arbitrum/ITokenGateway.sol"; +import { IBridgeEscrow } from "../../contracts/interfaces/IBridgeEscrow.sol"; +import { IGraphProxyAdmin } from "../../contracts/interfaces/IGraphProxyAdmin.sol"; +import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; + +import { GraphDirectory } from "./../../contracts/utilities/GraphDirectory.sol"; + +contract GraphDirectoryImplementation is GraphDirectory { + constructor(address controller) GraphDirectory(controller) {} + + function getContractFromController(bytes memory contractName) external view returns (address) { + return _graphController().getContractProxy(keccak256(contractName)); + } + function graphToken() external view returns (IGraphToken) { + return _graphToken(); + } + + function graphStaking() external view returns (IHorizonStaking) { + return _graphStaking(); + } + + function graphPayments() external view returns (IGraphPayments) { + return _graphPayments(); + } + + function graphPaymentsEscrow() external view returns (IPaymentsEscrow) { + return _graphPaymentsEscrow(); + } + + function graphController() external view returns (IController) { + return _graphController(); + } + + function graphEpochManager() external view returns (IEpochManager) { + return _graphEpochManager(); + } + + function graphRewardsManager() external view returns (IRewardsManager) { + return _graphRewardsManager(); + } + + function graphTokenGateway() external view returns (ITokenGateway) { + return _graphTokenGateway(); + } + + function graphBridgeEscrow() external view returns (IBridgeEscrow) { + return _graphBridgeEscrow(); + } + + function graphProxyAdmin() external view returns (IGraphProxyAdmin) { + return _graphProxyAdmin(); + } + + function graphCuration() external view returns (ICuration) { + return _graphCuration(); + } +} From ec7a3742f201ee0150c6bef7438e62a35d91aa6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 5 Jun 2024 17:05:56 -0300 Subject: [PATCH 111/277] test: add base data service tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 10 ++++-- .../test/data-service/DataService.t.sol | 31 +++++++++++++++++++ .../test/data-service/DataService.tree | 3 ++ .../test/data-service/DataServiceBase.sol | 18 +++++++++++ .../DataServiceBaseUpgradeable.sol | 27 ++++++++++++++++ 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 packages/horizon/test/data-service/DataService.t.sol create mode 100644 packages/horizon/test/data-service/DataService.tree create mode 100644 packages/horizon/test/data-service/DataServiceBase.sol create mode 100644 packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index db0a2bd11..8831237aa 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -16,8 +16,14 @@ import { ProvisionManager } from "./utilities/ProvisionManager.sol"; * * The derived contract MUST implement all the interfaces described in {IDataService} and in * accordance with the Data Service framework. - * @dev Implementation must initialize the contract using {__DataService_init} or - * {__DataService_init_unchained} functions. + * @dev A note on upgradeability: this base contract can be inherited by upgradeable or non upgradeable + * contracts. + * - If the data service implementation is upgradeable, it must initialize the contract via an external + * initializer function with the `initializer` modifier that calls {__DataService_init} or + * {__DataService_init_unchained}. + * - If the data service implementation is NOT upgradeable, it must initialize the contract by calling + * {__DataService_init} or {__DataService_init_unchained} in the constructor. Note that the `initializer` + * will be required in the constructor. */ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1Storage, IDataService { /** diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol new file mode 100644 index 000000000..a21d7f2e1 --- /dev/null +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import { GraphBaseTest } from "../GraphBase.t.sol"; +import { DataServiceBase } from "./DataServiceBase.sol"; + +contract DataService is GraphBaseTest { + function test_WhenTheContractIsDeployedWithAValidController() external { + DataServiceBase dataService = _deployDataService(); + + (uint32 minDelegationRatio, uint32 maxDelegationRatio) = dataService.getDelegationRatioRange(); + assertEq(minDelegationRatio, type(uint32).min); + assertEq(maxDelegationRatio, type(uint32).max); + + (uint256 minTokens, uint256 maxTokens) = dataService.getProvisionTokensRange(); + assertEq(minTokens, type(uint256).min); + assertEq(maxTokens, type(uint256).max); + + (uint32 minVerifierCut, uint32 maxVerifierCut) = dataService.getVerifierCutRange(); + assertEq(minVerifierCut, type(uint32).min); + assertEq(maxVerifierCut, type(uint32).max); + + (uint64 minThawingPeriod, uint64 maxThawingPeriod) = dataService.getThawingPeriodRange(); + assertEq(minThawingPeriod, type(uint64).min); + assertEq(maxThawingPeriod, type(uint64).max); + } + + function _deployDataService() internal returns (DataServiceBase) { + return new DataServiceBase(address(controller)); + } +} diff --git a/packages/horizon/test/data-service/DataService.tree b/packages/horizon/test/data-service/DataService.tree new file mode 100644 index 000000000..2a71bce48 --- /dev/null +++ b/packages/horizon/test/data-service/DataService.tree @@ -0,0 +1,3 @@ +DataService +└── when the contract is deployed with a valid controller + └── it should set all it's ranges to max \ No newline at end of file diff --git a/packages/horizon/test/data-service/DataServiceBase.sol b/packages/horizon/test/data-service/DataServiceBase.sol new file mode 100644 index 000000000..5103d51c5 --- /dev/null +++ b/packages/horizon/test/data-service/DataServiceBase.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { DataService } from "../../contracts/data-service/DataService.sol"; +import { IGraphPayments } from "./../../contracts/interfaces/IGraphPayments.sol"; + +contract DataServiceBase is DataService { + constructor(address controller) DataService(controller) initializer { + __DataService_init(); + } + + function register(address serviceProvider, bytes calldata data) external {} + function acceptProvision(address serviceProvider, bytes calldata data) external {} + function startService(address serviceProvider, bytes calldata data) external {} + function stopService(address serviceProvider, bytes calldata data) external {} + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + function slash(address serviceProvider, bytes calldata data) external {} +} diff --git a/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol b/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol new file mode 100644 index 000000000..91984def0 --- /dev/null +++ b/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { DataService } from "../../contracts/data-service/DataService.sol"; +import { IGraphPayments } from "./../../contracts/interfaces/IGraphPayments.sol"; + +contract DataServiceBase is DataService { + constructor(address controller) DataService(controller) { + _disableInitializers(); + } + + function initialize() external initializer { + __DataService_init(); + } + + function register(address serviceProvider, bytes calldata data) external {} + + function acceptProvision(address serviceProvider, bytes calldata data) external {} + + function startService(address serviceProvider, bytes calldata data) external {} + + function stopService(address serviceProvider, bytes calldata data) external {} + + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + + function slash(address serviceProvider, bytes calldata data) external {} +} From 82cc903e92f3a5af603358d52ce3debfd5a18b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 5 Jun 2024 17:26:28 -0300 Subject: [PATCH 112/277] test: add upgradeable data service test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .gitmodules | 3 ++ .../contracts/data-service/DataService.sol | 3 +- .../horizon/lib/openzeppelin-foundry-upgrades | 1 + packages/horizon/remappings.txt | 1 + .../test/data-service/DataService.t.sol | 2 +- .../DataServiceBaseUpgradeable.sol | 2 +- .../data-service/DataServiceUpgradeable.t.sol | 43 +++++++++++++++++++ 7 files changed, 52 insertions(+), 3 deletions(-) create mode 160000 packages/horizon/lib/openzeppelin-foundry-upgrades create mode 100644 packages/horizon/test/data-service/DataServiceUpgradeable.t.sol diff --git a/.gitmodules b/.gitmodules index 6e4ecf4c6..313d1d2d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "packages/horizon/lib/forge-std"] path = packages/horizon/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "packages/horizon/lib/openzeppelin-foundry-upgrades"] + path = packages/horizon/lib/openzeppelin-foundry-upgrades + url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index 8831237aa..40f375d6f 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -20,7 +20,8 @@ import { ProvisionManager } from "./utilities/ProvisionManager.sol"; * contracts. * - If the data service implementation is upgradeable, it must initialize the contract via an external * initializer function with the `initializer` modifier that calls {__DataService_init} or - * {__DataService_init_unchained}. + * {__DataService_init_unchained}. It's recommended the implementation constructor to also call + * {_disableInitializers} to prevent the implementation from being initialized. * - If the data service implementation is NOT upgradeable, it must initialize the contract by calling * {__DataService_init} or {__DataService_init_unchained} in the constructor. Note that the `initializer` * will be required in the constructor. diff --git a/packages/horizon/lib/openzeppelin-foundry-upgrades b/packages/horizon/lib/openzeppelin-foundry-upgrades new file mode 160000 index 000000000..4cd15fc50 --- /dev/null +++ b/packages/horizon/lib/openzeppelin-foundry-upgrades @@ -0,0 +1 @@ +Subproject commit 4cd15fc50b141c77d8cc9ff8efb44d00e841a299 diff --git a/packages/horizon/remappings.txt b/packages/horizon/remappings.txt index aa8b4e6b7..d27549557 100644 --- a/packages/horizon/remappings.txt +++ b/packages/horizon/remappings.txt @@ -5,3 +5,4 @@ eth-gas-reporter/=node_modules/eth-gas-reporter/ hardhat/=node_modules/hardhat/ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ @openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/ +openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src \ No newline at end of file diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol index a21d7f2e1..738e2112d 100644 --- a/packages/horizon/test/data-service/DataService.t.sol +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { GraphBaseTest } from "../GraphBase.t.sol"; import { DataServiceBase } from "./DataServiceBase.sol"; -contract DataService is GraphBaseTest { +contract DataServiceTest is GraphBaseTest { function test_WhenTheContractIsDeployedWithAValidController() external { DataServiceBase dataService = _deployDataService(); diff --git a/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol b/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol index 91984def0..00f2b485b 100644 --- a/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol +++ b/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { DataService } from "../../contracts/data-service/DataService.sol"; import { IGraphPayments } from "./../../contracts/interfaces/IGraphPayments.sol"; -contract DataServiceBase is DataService { +contract DataServiceBaseUpgradeable is DataService { constructor(address controller) DataService(controller) { _disableInitializers(); } diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol new file mode 100644 index 000000000..5523d7286 --- /dev/null +++ b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import { GraphBaseTest } from "../GraphBase.t.sol"; +import { DataServiceBaseUpgradeable } from "./DataServiceBaseUpgradeable.sol"; +import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +contract DataServiceUpgradeableTest is GraphBaseTest { + function test_WhenTheContractIsDeployedWithAValidController() external { + DataServiceBaseUpgradeable dataService = _deployDataService(); + + (uint32 minDelegationRatio, uint32 maxDelegationRatio) = dataService.getDelegationRatioRange(); + assertEq(minDelegationRatio, type(uint32).min); + assertEq(maxDelegationRatio, type(uint32).max); + + (uint256 minTokens, uint256 maxTokens) = dataService.getProvisionTokensRange(); + assertEq(minTokens, type(uint256).min); + assertEq(maxTokens, type(uint256).max); + + (uint32 minVerifierCut, uint32 maxVerifierCut) = dataService.getVerifierCutRange(); + assertEq(minVerifierCut, type(uint32).min); + assertEq(maxVerifierCut, type(uint32).max); + + (uint64 minThawingPeriod, uint64 maxThawingPeriod) = dataService.getThawingPeriodRange(); + assertEq(minThawingPeriod, type(uint64).min); + assertEq(maxThawingPeriod, type(uint64).max); + } + + function _deployDataService() internal returns (DataServiceBaseUpgradeable) { + // Deploy implementation + address implementation = address(new DataServiceBaseUpgradeable(address(controller))); + + // Deploy proxy (calls initialize) + address proxy = UnsafeUpgrades.deployTransparentProxy( + implementation, + users.governor, + abi.encodeCall(DataServiceBaseUpgradeable.initialize, ()) + ); + + return DataServiceBaseUpgradeable(proxy); + } +} From 9c6f70f82474cdf1239c191363bf6dbab4012aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 7 Jun 2024 14:45:46 +0200 Subject: [PATCH 113/277] fix: bad import path for graph directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/subgraph-service/contracts/DisputeManager.sol | 2 +- .../subgraph-service/contracts/utilities/AllocationManager.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 765d08fbc..692c6a93c 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -14,7 +14,7 @@ import { Attestation } from "./libraries/Attestation.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; +import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/GraphDirectory.sol"; import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; import { AttestationManager } from "./utilities/AttestationManager.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 7b8ba6c50..8d14da240 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; -import { GraphDirectory } from "@graphprotocol/horizon/contracts/data-service/GraphDirectory.sol"; +import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/GraphDirectory.sol"; import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; From 9cb27fe2602e93fa4f3ecbb68eef763f68569f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 7 Jun 2024 17:49:11 +0200 Subject: [PATCH 114/277] fix: feedback fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/contracts/contracts/arbitrum/ITokenGateway.sol | 4 ++-- packages/horizon/contracts/data-service/DataService.sol | 5 ++--- .../data-service/extensions/DataServiceFees.sol | 4 ++-- .../contracts/data-service/interfaces/IDataService.sol | 9 ++++++--- packages/horizon/contracts/libraries/LinkedList.sol | 8 ++++---- packages/horizon/contracts/staking/HorizonStaking.sol | 2 +- packages/horizon/test/libraries/LinkedList.t.sol | 6 +++--- packages/horizon/test/libraries/ListImplementation.sol | 2 +- packages/subgraph-service/contracts/SubgraphService.sol | 6 +++--- 9 files changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/contracts/contracts/arbitrum/ITokenGateway.sol index 9fb440fd2..96080858c 100644 --- a/packages/contracts/contracts/arbitrum/ITokenGateway.sol +++ b/packages/contracts/contracts/arbitrum/ITokenGateway.sol @@ -47,8 +47,8 @@ interface ITokenGateway { // ); function outboundTransfer( - address oken, - address t, + address token, + address to, uint256 amunt, uint256 maxas, uint256 gasPiceBid, diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index 40f375d6f..b2bc32d95 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -38,6 +38,7 @@ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1 */ // solhint-disable-next-line func-name-mixedcase function __DataService_init() internal onlyInitializing { + __ProvisionManager_init_unchained(); __DataService_init_unchained(); } @@ -45,7 +46,5 @@ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1 * @notice Initializes the contract. */ // solhint-disable-next-line func-name-mixedcase - function __DataService_init_unchained() internal onlyInitializing { - __ProvisionManager_init_unchained(); - } + function __DataService_init_unchained() internal onlyInitializing {} } diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 1c81da824..1ffabce2c 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -22,7 +22,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat /** * @notice See {IDataServiceFees-releaseStake} */ - function releaseStake(uint256 n) external virtual { + function releaseStake(uint256 n) external virtual override { _releaseStake(msg.sender, n); } @@ -52,7 +52,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat nextClaim: bytes32(0) }); if (claimsList.count != 0) claims[claimsList.tail].nextClaim = claimId; - claimsList.add(claimId); + claimsList.addTail(claimId); emit StakeClaimLocked(_serviceProvider, claimId, _tokens, _unlockTimestamp); } diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index f2ffec1a5..69b4fdf1c 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -17,8 +17,9 @@ interface IDataService { /** * @notice Emitted when a service provider is registered with the data service. * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. */ - event ServiceProviderRegistered(address indexed serviceProvider); + event ServiceProviderRegistered(address indexed serviceProvider, bytes data); /** * @notice Emitted when a service provider accepts a provision in {Graph Horizon staking contract}. @@ -29,14 +30,16 @@ interface IDataService { /** * @notice Emitted when a service provider starts providing the service. * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. */ - event ServiceStarted(address indexed serviceProvider); + event ServiceStarted(address indexed serviceProvider, bytes data); /** * @notice Emitted when a service provider stops providing the service. * @param serviceProvider The address of the service provider. + * @param data Custom data, usage defined by the data service. */ - event ServiceStopped(address indexed serviceProvider); + event ServiceStopped(address indexed serviceProvider, bytes data); /** * @notice Emitted when a service provider collects payment. diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index 7a49d0c5a..27a22a08f 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -63,7 +63,7 @@ library LinkedList { * @param self The list metadata * @param id The id of the item to add */ - function add(List storage self, bytes32 id) internal { + function addTail(List storage self, bytes32 id) internal { require(self.count < MAX_ITEMS, LinkedListMaxElementsExceeded()); self.tail = id; self.nonce += 1; @@ -80,7 +80,7 @@ library LinkedList { * @param deleteItem A function to delete an item. This should delete the item from * the contract storage. It takes the id of the item to delete. */ - function remove( + function removeHead( List storage self, function(bytes32) view returns (bytes32) getNextItem, function(bytes32) deleteItem @@ -96,13 +96,13 @@ library LinkedList { /** * @notice Traverses the list and processes each item. + * It deletes the processed items from both the list and the storage mapping. * @param self The list metadata * @param getNextItem A function to get the next item in the list. It should take * the id of the current item and return the id of the next item. * @param processItem A function to process an item. The function should take the id of the item * and an accumulator, and return: * - a boolean indicating whether the traversal should stop - * - a boolean indicating whether the item should be deleted * - an accumulator to pass data between iterations * @param deleteItem A function to delete an item. This should delete the item from * the contract storage. It takes the id of the item to delete. @@ -132,7 +132,7 @@ library LinkedList { if (shouldBreak) break; acc = acc_; - cursor = self.remove(getNextItem, deleteItem); + cursor = self.removeHead(getNextItem, deleteItem); if (!traverseAll) iterations--; itemCount++; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 4caa10a96..d63b655c2 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -830,7 +830,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _thawRequests[thawRequestId] = ThawRequest({ shares: _shares, thawingUntil: _thawingUntil, next: bytes32(0) }); if (thawRequestList.count != 0) _thawRequests[thawRequestList.tail].next = thawRequestId; - thawRequestList.add(thawRequestId); + thawRequestList.addTail(thawRequestId); emit ThawRequestCreated(_serviceProvider, _verifier, _owner, _shares, _thawingUntil, thawRequestId); return thawRequestId; diff --git a/packages/horizon/test/libraries/LinkedList.t.sol b/packages/horizon/test/libraries/LinkedList.t.sol index 63229fb2c..d2cf60aef 100644 --- a/packages/horizon/test/libraries/LinkedList.t.sol +++ b/packages/horizon/test/libraries/LinkedList.t.sol @@ -33,12 +33,12 @@ contract LinkedListTest is Test, ListImplementation { } vm.expectRevert(LinkedList.LinkedListMaxElementsExceeded.selector); - list.add(_buildItemId(list.nonce)); + list.addTail(_buildItemId(list.nonce)); } function test_Remove_RevertGiven_TheListIsEmpty() external { vm.expectRevert(LinkedList.LinkedListEmptyList.selector); - list.remove(_getNextItem, _deleteItem); + list.removeHead(_getNextItem, _deleteItem); } function test_Remove_GivenTheListIsNotEmpty() external { @@ -119,7 +119,7 @@ contract LinkedListTest is Test, ListImplementation { Item memory beforeHeadItem = items[beforeHead]; - list.remove(_getNextItem, _deleteItem); + list.removeHead(_getNextItem, _deleteItem); uint256 afterNonce = list.nonce; uint256 afterCount = list.count; diff --git a/packages/horizon/test/libraries/ListImplementation.sol b/packages/horizon/test/libraries/ListImplementation.sol index 0ec024435..9c8bbfb60 100644 --- a/packages/horizon/test/libraries/ListImplementation.sol +++ b/packages/horizon/test/libraries/ListImplementation.sol @@ -22,7 +22,7 @@ contract ListImplementation { if (_list.count != 0) { items[_list.tail].next = _id; } - _list.add(_id); + _list.addTail(_id); return _id; } diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index fb113c24c..e127abd3d 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -128,7 +128,7 @@ contract SubgraphService is _setRewardsDestination(indexer, rewardsDestination); } - emit ServiceProviderRegistered(indexer); + emit ServiceProviderRegistered(indexer, data); } /** @@ -193,7 +193,7 @@ contract SubgraphService is (bytes32, uint256, address, bytes) ); _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof, maximumDelegationRatio); - emit ServiceStarted(indexer); + emit ServiceStarted(indexer, data); } /** @@ -221,7 +221,7 @@ contract SubgraphService is ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { address allocationId = abi.decode(data, (address)); _closeAllocation(allocationId); - emit ServiceStopped(indexer); + emit ServiceStopped(indexer, data); } /** From a7d8ec470df2edbd7a4c6289bce80435af5dc347 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:34:03 -0300 Subject: [PATCH 115/277] chore: horizon allocation fix and tests (#981) --- .../internal/IHorizonStakingExtension.sol | 4 +- .../horizon/contracts/mocks/CurationMock.sol | 22 +++ .../contracts/mocks/EpochManagerMock.sol | 64 ++++++++ .../contracts/mocks/RewardsManagerMock.sol | 27 ++++ .../staking/HorizonStakingExtension.sol | 11 +- packages/horizon/test/GraphBase.t.sol | 37 +++-- .../allocation/HorizonStakingExtension.t.sol | 80 +++++++++ .../test/staking/allocation/allocation.t.sol | 114 +++++++++++++ .../test/staking/allocation/close.t.sol | 72 +++++++++ .../test/staking/allocation/collect.t.sol | 153 ++++++++++++++++++ packages/horizon/test/utils/Constants.sol | 4 + 11 files changed, 569 insertions(+), 19 deletions(-) create mode 100644 packages/horizon/contracts/mocks/CurationMock.sol create mode 100644 packages/horizon/contracts/mocks/EpochManagerMock.sol create mode 100644 packages/horizon/contracts/mocks/RewardsManagerMock.sol create mode 100644 packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol create mode 100644 packages/horizon/test/staking/allocation/close.t.sol create mode 100644 packages/horizon/test/staking/allocation/collect.t.sol diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index a51b1871d..3c9a26c91 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -2,11 +2,13 @@ pragma solidity 0.8.26; +import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; + /** * @title Interface for {HorizonStakingExtension} contract. * @notice Provides functions for managing legacy allocations and transfer tools. */ -interface IHorizonStakingExtension { +interface IHorizonStakingExtension is IRewardsIssuer { /** * @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() diff --git a/packages/horizon/contracts/mocks/CurationMock.sol b/packages/horizon/contracts/mocks/CurationMock.sol new file mode 100644 index 000000000..b480673fd --- /dev/null +++ b/packages/horizon/contracts/mocks/CurationMock.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.26; + +import { MockGRTToken } from "./MockGRTToken.sol"; + +contract CurationMock { + + mapping(bytes32 => uint256) public curation; + + function signal(bytes32 _subgraphDeploymentID, uint256 _tokens) public { + curation[_subgraphDeploymentID] += _tokens; + } + + function isCurated(bytes32 _subgraphDeploymentID) public view returns (bool) { + return curation[_subgraphDeploymentID] != 0; + } + + function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external { + curation[_subgraphDeploymentID] += _tokens; + } +} diff --git a/packages/horizon/contracts/mocks/EpochManagerMock.sol b/packages/horizon/contracts/mocks/EpochManagerMock.sol new file mode 100644 index 000000000..82b51d855 --- /dev/null +++ b/packages/horizon/contracts/mocks/EpochManagerMock.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.26; + +import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; + +contract EpochManagerMock is IEpochManager { + + // -- Variables -- + + uint256 public epochLength; + uint256 public lastRunEpoch; + uint256 public lastLengthUpdateEpoch; + uint256 public lastLengthUpdateBlock; + + // -- Configuration -- + + function setEpochLength(uint256 _epochLength) public { + lastLengthUpdateEpoch = 1; + lastLengthUpdateBlock = blockNum(); + epochLength = _epochLength; + } + + // -- Epochs + + function runEpoch() public { + lastRunEpoch = currentEpoch(); + } + + // -- Getters -- + + function isCurrentEpochRun() public view returns (bool) { + return lastRunEpoch == currentEpoch(); + } + + function blockNum() public view returns (uint256) { + return block.number; + } + + function blockHash(uint256 _block) public view returns (bytes32) { + return blockhash(_block); + } + + function currentEpoch() public view returns (uint256) { + return lastLengthUpdateEpoch + epochsSinceUpdate(); + } + + function currentEpochBlock() public view returns (uint256) { + return lastLengthUpdateBlock + (epochsSinceUpdate() * epochLength); + } + + function currentEpochBlockSinceStart() public view returns (uint256) { + return blockNum() - currentEpochBlock(); + } + + function epochsSince(uint256 _epoch) public view returns (uint256) { + uint256 epoch = currentEpoch(); + return _epoch < epoch ? (epoch - _epoch) : 0; + } + + function epochsSinceUpdate() public view returns (uint256) { + return (blockNum() - lastLengthUpdateBlock) / epochLength; + } +} diff --git a/packages/horizon/contracts/mocks/RewardsManagerMock.sol b/packages/horizon/contracts/mocks/RewardsManagerMock.sol new file mode 100644 index 000000000..9473e6dbc --- /dev/null +++ b/packages/horizon/contracts/mocks/RewardsManagerMock.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.26; + +import { MockGRTToken } from "./MockGRTToken.sol"; + +contract RewardsManagerMock { + + // -- Variables -- + MockGRTToken public token; + uint256 private rewards; + + // -- Constructor -- + + constructor(MockGRTToken _token, uint256 _rewards) { + token = _token; + rewards = _rewards; + } + + function takeRewards(address) external returns (uint256) { + token.mint(msg.sender, rewards); + return rewards; + } + + function onSubgraphAllocationUpdate(bytes32) public returns (uint256) {} + function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external returns (uint256) {} +} diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 7683523a7..7abac7623 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.26; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; -import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingExtension } from "../interfaces/internal/IHorizonStakingExtension.sol"; import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; @@ -26,7 +25,7 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * @dev TODO: Once the transition period and the transfer tools are deemed not necessary this contract * can be removed. It's expected the transition period to last for a full allocation cycle (28 epochs). */ -contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2StakingBase, IHorizonStakingExtension { +contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizonStakingExtension { using TokenUtils for IGraphToken; using PPMMath for uint256; @@ -442,9 +441,9 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki // Anyone is allowed to close ONLY under two concurrent conditions // - After maxAllocationEpochs passed // - When the allocation is for non-zero amount of tokens - bool isIndexer = isOperator(alloc.indexer, SUBGRAPH_DATA_SERVICE_ADDRESS); + bool isIndexerOrOperator = msg.sender == alloc.indexer || isOperator(alloc.indexer, SUBGRAPH_DATA_SERVICE_ADDRESS); if (epochs <= __DEPRECATED_maxAllocationEpochs || alloc.tokens == 0) { - require(isIndexer, "!auth"); + require(isIndexerOrOperator, "!auth"); } // Close the allocation @@ -455,7 +454,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki // Process non-zero-allocation rewards tracking if (alloc.tokens > 0) { // Distribute rewards if proof of indexing was presented by the indexer or operator - if (isIndexer && _poi != 0) { + if (isIndexerOrOperator && _poi != 0) { _distributeRewards(_allocationID, alloc.indexer); } else { _updateRewards(alloc.subgraphDeploymentID); @@ -481,7 +480,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IRewardsIssuer, IL2Staki _allocationID, msg.sender, _poi, - !isIndexer + !isIndexerOrOperator ); } diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index e21a13142..c7f57197a 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -13,6 +13,9 @@ import { IHorizonStaking } from "contracts/interfaces/IHorizonStaking.sol"; import { HorizonStaking } from "contracts/staking/HorizonStaking.sol"; import { HorizonStakingExtension } from "contracts/staking/HorizonStakingExtension.sol"; import { MockGRTToken } from "../contracts/mocks/MockGRTToken.sol"; +import { EpochManagerMock } from "../contracts/mocks/EpochManagerMock.sol"; +import { RewardsManagerMock } from "../contracts/mocks/RewardsManagerMock.sol"; +import { CurationMock } from "../contracts/mocks/CurationMock.sol"; import { Constants } from "./utils/Constants.sol"; import { Users } from "./utils/Users.sol"; import { Utils } from "./utils/Utils.sol"; @@ -31,6 +34,9 @@ abstract contract GraphBaseTest is Utils, Constants { GraphPayments public payments; PaymentsEscrow public escrow; IHorizonStaking public staking; + EpochManagerMock public epochManager; + RewardsManagerMock public rewardsManager; + CurationMock public curation; HorizonStaking private stakingBase; HorizonStakingExtension private stakingExtension; @@ -84,10 +90,9 @@ abstract contract GraphBaseTest is Utils, Constants { vm.startPrank(users.governor); proxyAdmin = new GraphProxyAdmin(); controller = new Controller(); - vm.stopPrank(); // Staking Proxy - vm.prank(users.deployer); + resetPrank(users.deployer); GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); // GraphPayments predict address @@ -118,21 +123,29 @@ abstract contract GraphBaseTest is Utils, Constants { users.deployer ); + // Epoch Manager + epochManager = new EpochManagerMock(); + + // Rewards Manager + rewardsManager = new RewardsManagerMock(token, ALLOCATIONS_REWARD_CUT); + + // Curation + curation = new CurationMock(); + // Setup controller - vm.startPrank(users.governor); + resetPrank(users.governor); controller.setContractProxy(keccak256("GraphToken"), address(token)); controller.setContractProxy(keccak256("PaymentsEscrow"), predictedAddressEscrow); controller.setContractProxy(keccak256("GraphPayments"), predictedPaymentsAddress); controller.setContractProxy(keccak256("Staking"), address(stakingProxy)); - controller.setContractProxy(keccak256("EpochManager"), makeAddr("EpochManager")); - controller.setContractProxy(keccak256("RewardsManager"), makeAddr("RewardsManager")); - controller.setContractProxy(keccak256("Curation"), makeAddr("Curation")); + controller.setContractProxy(keccak256("EpochManager"), address(epochManager)); + controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); + controller.setContractProxy(keccak256("Curation"), address(curation)); controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); controller.setContractProxy(keccak256("BridgeEscrow"), makeAddr("BridgeEscrow")); controller.setContractProxy(keccak256("GraphProxyAdmin"), address(proxyAdmin)); - vm.stopPrank(); - vm.startPrank(users.deployer); + resetPrank(users.deployer); payments = new GraphPayments{salt: saltPayments}( address(controller), protocolPaymentCut @@ -151,21 +164,21 @@ abstract contract GraphBaseTest is Utils, Constants { address(stakingExtension), subgraphDataServiceLegacyAddress ); - vm.stopPrank(); - vm.startPrank(users.governor); + resetPrank(users.governor); proxyAdmin.upgrade(stakingProxy, address(stakingBase)); proxyAdmin.acceptProxy(stakingBase, stakingProxy); staking = IHorizonStaking(address(stakingProxy)); } function setupProtocol() private { - vm.startPrank(users.governor); + resetPrank(users.governor); staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); + epochManager.setEpochLength(EPOCH_LENGTH); } function unpauseProtocol() private { - vm.startPrank(users.governor); + resetPrank(users.governor); controller.setPaused(false); } diff --git a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol new file mode 100644 index 000000000..266ec3c5b --- /dev/null +++ b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; + +contract HorizonStakingExtensionTest is HorizonStakingTest { + + /* + * VARIABLES + */ + + address internal _allocationId = makeAddr("allocationId"); + bytes32 internal constant _subgraphDeploymentID = keccak256("subgraphDeploymentID"); + bytes32 internal constant _poi = keccak256("poi"); + uint256 internal constant MAX_ALLOCATION_EPOCHS = 28; + IHorizonStakingExtension.Allocation internal _allocation; + + /* + * MODIFIERS + */ + + modifier useAllocation() { + _storeAllocation(0); + _; + } + + /* + * SET UP + */ + + function setUp() public virtual override { + super.setUp(); + + _allocation = IHorizonStakingExtension.Allocation({ + indexer: users.indexer, + subgraphDeploymentID: _subgraphDeploymentID, + tokens: 0, + createdAtEpoch: block.timestamp, + closedAtEpoch: 0, + collectedFees: 0, + __DEPRECATED_effectiveAllocation: 0, + accRewardsPerAllocatedToken: 0, + distributedRebates: 0 + }); + } + + /* + * HELPERS + */ + + function _storeAllocation(uint256 tokens) internal { + uint256 allocationsSlot = 15; + bytes32 allocationBaseSlot = keccak256(abi.encode(_allocationId, allocationsSlot)); + vm.store(address(staking), allocationBaseSlot, bytes32(uint256(uint160(_allocation.indexer)))); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 1), _allocation.subgraphDeploymentID); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 2), bytes32(tokens)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 3), bytes32(_allocation.createdAtEpoch)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 4), bytes32(_allocation.closedAtEpoch)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 5), bytes32(_allocation.collectedFees)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 6), bytes32(_allocation.__DEPRECATED_effectiveAllocation)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 7), bytes32(_allocation.accRewardsPerAllocatedToken)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 8), bytes32(_allocation.distributedRebates)); + + uint256 serviceProviderSlot = 14; + bytes32 serviceProviderBaseSlot = keccak256(abi.encode(_allocation.indexer, serviceProviderSlot)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 1), bytes32(tokens)); + + uint256 subgraphsAllocationsSlot = 16; + bytes32 subgraphAllocationsBaseSlot = keccak256(abi.encode(_allocation.subgraphDeploymentID, subgraphsAllocationsSlot)); + vm.store(address(staking), subgraphAllocationsBaseSlot, bytes32(tokens)); + } + + function _storeMaxAllocationEpochs() internal { + uint256 slot = 13; + vm.store(address(staking), bytes32(slot), bytes32(MAX_ALLOCATION_EPOCHS) << 128); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/allocation.t.sol b/packages/horizon/test/staking/allocation/allocation.t.sol index e69de29bb..1667c607c 100644 --- a/packages/horizon/test/staking/allocation/allocation.t.sol +++ b/packages/horizon/test/staking/allocation/allocation.t.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingExtensionTest } from "./HorizonStakingExtension.t.sol"; +import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; + +contract HorizonStakingAllocationTest is HorizonStakingExtensionTest { + + /* + * TESTS + */ + + function testAllocation_GetAllocation() public useAllocation { + IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); + assertEq(allocation.indexer, _allocation.indexer); + assertEq(allocation.subgraphDeploymentID, _allocation.subgraphDeploymentID); + assertEq(allocation.tokens, _allocation.tokens); + assertEq(allocation.createdAtEpoch, _allocation.createdAtEpoch); + assertEq(allocation.closedAtEpoch, _allocation.closedAtEpoch); + assertEq(allocation.collectedFees, _allocation.collectedFees); + assertEq(allocation.__DEPRECATED_effectiveAllocation, _allocation.__DEPRECATED_effectiveAllocation); + assertEq(allocation.accRewardsPerAllocatedToken, _allocation.accRewardsPerAllocatedToken); + assertEq(allocation.distributedRebates, _allocation.distributedRebates); + } + + function testAllocation_GetAllocationData() public useAllocation { + (address indexer, bytes32 subgraphDeploymentID, uint256 tokens, uint256 accRewardsPerAllocatedToken) = + staking.getAllocationData(_allocationId); + assertEq(indexer, _allocation.indexer); + assertEq(subgraphDeploymentID, _allocation.subgraphDeploymentID); + assertEq(tokens, _allocation.tokens); + assertEq(accRewardsPerAllocatedToken, _allocation.accRewardsPerAllocatedToken); + } + + function testAllocation_GetAllocationState_Active() public useAllocation { + IHorizonStakingExtension.AllocationState state = staking.getAllocationState(_allocationId); + assertEq(uint16(state), uint16(IHorizonStakingExtension.AllocationState.Active)); + } + + function testAllocation_GetAllocationState_Null() public view { + IHorizonStakingExtension.AllocationState state = staking.getAllocationState(_allocationId); + assertEq(uint16(state), uint16(IHorizonStakingExtension.AllocationState.Null)); + } + + function testAllocation_IsAllocation() public useAllocation { + bool isAllocation = staking.isAllocation(_allocationId); + assertTrue(isAllocation); + } + + function testAllocation_IsNotAllocation() public view { + bool isAllocation = staking.isAllocation(_allocationId); + assertFalse(isAllocation); + } + + function testCloseAllocation(uint256 tokens) public useIndexer { + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + _storeAllocation(tokens); + _storeMaxAllocationEpochs(); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + + // Skip 15 epochs + vm.roll(15); + + staking.closeAllocation(_allocationId, _poi); + IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); + assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); + + // Stake should be updated with rewards + assertEq(staking.getStake(address(users.indexer)), tokens + ALLOCATIONS_REWARD_CUT); + } + + function testCloseAllocation_RevertWhen_NotActive() public { + vm.expectRevert("!active"); + staking.closeAllocation(_allocationId, _poi); + } + + function testCloseAllocation_RevertWhen_NotIndexer() public useAllocation { + resetPrank(users.delegator); + vm.expectRevert("!auth"); + staking.closeAllocation(_allocationId, _poi); + } + + function testCloseAllocation_AfterMaxEpochs_AnyoneCanClose(uint256 tokens) public useIndexer { + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + _storeAllocation(tokens); + _storeMaxAllocationEpochs(); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + + // Skip to over the max allocation epochs + vm.roll(MAX_ALLOCATION_EPOCHS + 2); + + resetPrank(users.delegator); + staking.closeAllocation(_allocationId, 0x0); + IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); + assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); + + // No rewards distributed + assertEq(staking.getStake(address(users.indexer)), tokens); + } + + function testCloseAllocation_RevertWhen_ZeroTokensNotAuthorized() public useIndexer { + _storeAllocation(0); + _storeMaxAllocationEpochs(); + + // Skip to over the max allocation epochs + vm.roll(MAX_ALLOCATION_EPOCHS + 2); + + resetPrank(users.delegator); + vm.expectRevert("!auth"); + staking.closeAllocation(_allocationId, 0x0); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/close.t.sol b/packages/horizon/test/staking/allocation/close.t.sol new file mode 100644 index 000000000..21eb5a23e --- /dev/null +++ b/packages/horizon/test/staking/allocation/close.t.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingExtensionTest } from "./HorizonStakingExtension.t.sol"; +import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; + +contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { + + /* + * TESTS + */ + + function testCloseAllocation(uint256 tokens) public useIndexer { + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + _storeAllocation(tokens); + _storeMaxAllocationEpochs(); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + + // Skip 15 epochs + vm.roll(15); + + staking.closeAllocation(_allocationId, _poi); + IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); + assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); + + // Stake should be updated with rewards + assertEq(staking.getStake(address(users.indexer)), tokens + ALLOCATIONS_REWARD_CUT); + } + + function testCloseAllocation_RevertWhen_NotActive() public { + vm.expectRevert("!active"); + staking.closeAllocation(_allocationId, _poi); + } + + function testCloseAllocation_RevertWhen_NotIndexer() public useAllocation { + resetPrank(users.delegator); + vm.expectRevert("!auth"); + staking.closeAllocation(_allocationId, _poi); + } + + function testCloseAllocation_AfterMaxEpochs_AnyoneCanClose(uint256 tokens) public useIndexer { + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + _storeAllocation(tokens); + _storeMaxAllocationEpochs(); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + + // Skip to over the max allocation epochs + vm.roll(MAX_ALLOCATION_EPOCHS + 2); + + resetPrank(users.delegator); + staking.closeAllocation(_allocationId, 0x0); + IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); + assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); + + // No rewards distributed + assertEq(staking.getStake(address(users.indexer)), tokens); + } + + function testCloseAllocation_RevertWhen_ZeroTokensNotAuthorized() public useIndexer { + _storeAllocation(0); + _storeMaxAllocationEpochs(); + + // Skip to over the max allocation epochs + vm.roll(MAX_ALLOCATION_EPOCHS + 2); + + resetPrank(users.delegator); + vm.expectRevert("!auth"); + staking.closeAllocation(_allocationId, 0x0); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/collect.t.sol b/packages/horizon/test/staking/allocation/collect.t.sol new file mode 100644 index 000000000..ea4d1abcf --- /dev/null +++ b/packages/horizon/test/staking/allocation/collect.t.sol @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingExtensionTest } from "./HorizonStakingExtension.t.sol"; +import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; +import { ExponentialRebates } from "../../../contracts/staking/libraries/ExponentialRebates.sol"; +import { PPMMath } from "../../../contracts/libraries/PPMMath.sol"; + +contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { + using PPMMath for uint256; + + uint32 private alphaNumerator = 100; + uint32 private alphaDenominator = 100; + uint32 private lambdaNumerator = 60; + uint32 private lambdaDenominator = 100; + + /* + * MODIFIERS + */ + + modifier useRebateParameters() { + _storeRebateParameters(); + _; + } + + /* + * HELPERS + */ + + function _storeRebateParameters() private { + // Store alpha numerator and denominator + uint256 alphaSlot = 13; + uint256 alphaNumeratorOffset = 20; + uint256 alphaDenominatorOffset = 24; + bytes32 alphaValues = bytes32( + (uint256(alphaNumerator) << (8 * alphaNumeratorOffset)) | + (uint256(alphaDenominator) << (8 * alphaDenominatorOffset)) + ); + vm.store(address(staking), bytes32(alphaSlot), alphaValues); + + // Store lambda numerator and denominator + uint256 lambdaSlot = 25; + uint256 lambdaNumeratorOffset = 20; + uint256 lambdaDenominatorOffset = 24; + bytes32 lambdaValues = bytes32( + (uint256(lambdaNumerator) << (8 * lambdaNumeratorOffset)) | + (uint256(lambdaDenominator) << (8 * lambdaDenominatorOffset)) + ); + vm.store(address(staking), bytes32(lambdaSlot), lambdaValues); + } + + function _storeProtocolTaxAndCuration(uint32 curationPercentage, uint32 taxPercentage) private { + bytes32 slot = bytes32(uint256(13)); + uint256 curationOffset = 4; + uint256 protocolTaxOffset = 8; + bytes32 originalValue = vm.load(address(staking), slot); + + bytes32 newProtocolTaxValue = bytes32( + (uint256(originalValue) & ~((0xFFFFFFFF << (8 * curationOffset)) | (0xFFFFFFFF << (8 * protocolTaxOffset))) | + (uint256(curationPercentage) << (8 * curationOffset))) | + (uint256(taxPercentage) << (8 * protocolTaxOffset)) + ); + vm.store(address(staking), slot, newProtocolTaxValue); + } + + function _storeDelegationPool(uint256 tokens, uint32 queryFeeCut) private { + bytes32 baseSlot = keccak256(abi.encode(users.indexer, uint256(20))); + bytes32 queryFeeCutValue = bytes32(uint256(queryFeeCut) << uint256(64)); + bytes32 tokensSlot = bytes32(uint256(baseSlot) + 2); + vm.store(address(staking), baseSlot, queryFeeCutValue); + vm.store(address(staking), tokensSlot, bytes32(tokens)); + } + + /* + * TESTS + */ + + function testCollectAllocation_RevertWhen_InvalidAllocationId(uint256 tokens) public useAllocation { + vm.expectRevert("!alloc"); + staking.collect(tokens, address(0)); + } + + function testCollectAllocation_RevertWhen_Null(uint256 tokens) public { + vm.expectRevert("!collect"); + staking.collect(tokens, _allocationId); + } + + function testCollectAllocation_ZeroTokens() public useAllocation { + staking.collect(0, _allocationId); + assertEq(staking.getStake(address(users.indexer)), 0); + } + + function testCollect_Tokens( + uint256 provisionTokens, + uint256 allocationTokens, + uint256 collectTokens, + uint256 curationTokens, + uint32 curationPercentage, + uint32 protocolTaxPercentage, + uint256 delegationTokens, + uint32 queryFeeCut + ) public useRebateParameters { + provisionTokens = bound(provisionTokens, 1, MAX_STAKING_TOKENS); + allocationTokens = bound(allocationTokens, 0, MAX_STAKING_TOKENS); + collectTokens = bound(collectTokens, 0, MAX_STAKING_TOKENS); + curationTokens = bound(curationTokens, 0, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 0, MAX_STAKING_TOKENS); + vm.assume(curationPercentage <= MAX_PPM); + vm.assume(protocolTaxPercentage <= MAX_PPM); + vm.assume(queryFeeCut <= MAX_PPM); + resetPrank(users.indexer); + _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); + _storeAllocation(allocationTokens); + _storeProtocolTaxAndCuration(curationPercentage, protocolTaxPercentage); + _storeDelegationPool(delegationTokens, queryFeeCut); + curation.signal(_subgraphDeploymentID, curationTokens); + + resetPrank(users.gateway); + approve(address(staking), collectTokens); + staking.collect(collectTokens, _allocationId); + + uint256 protocolTaxTokens = collectTokens.mulPPMRoundUp(protocolTaxPercentage); + uint256 queryFees = collectTokens - protocolTaxTokens; + + uint256 curationCutTokens = 0; + if (curationTokens > 0) { + curationCutTokens = queryFees.mulPPMRoundUp(curationPercentage); + queryFees -= curationCutTokens; + } + + uint256 newRebates = ExponentialRebates.exponentialRebates( + queryFees, + allocationTokens, + alphaNumerator, + alphaDenominator, + lambdaNumerator, + lambdaDenominator + ); + uint256 payment = newRebates > queryFees ? queryFees : newRebates; + + uint256 delegationFeeCut = 0; + if (delegationTokens > 0) { + delegationFeeCut = payment - payment.mulPPM(queryFeeCut); + payment -= delegationFeeCut; + } + + assertEq(staking.getStake(address(users.indexer)), provisionTokens + payment); + assertEq(curation.curation(_subgraphDeploymentID), curationTokens + curationCutTokens); + assertEq(staking.getDelegationPool(users.indexer, subgraphDataServiceLegacyAddress).tokens, delegationTokens + delegationFeeCut); + } +} \ No newline at end of file diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index f3e7f1157..a5fc1fe27 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -15,4 +15,8 @@ abstract contract Constants { uint32 internal constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% in parts per million uint64 internal constant MAX_THAWING_PERIOD = 28 days; uint256 internal constant MIN_DELEGATION = 1 ether; + // Epoch manager + uint256 internal constant EPOCH_LENGTH = 1; + // Rewards manager + uint256 internal constant ALLOCATIONS_REWARD_CUT = 100 ether; } \ No newline at end of file From 04bf4c7dfa0b1f30b0ea1bffcd7ee615879d9355 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 7 Jun 2024 17:49:40 -0300 Subject: [PATCH 116/277] chore: horizon allocation with beneficiary test --- .../allocation/HorizonStakingExtension.t.sol | 6 ++ .../test/staking/allocation/allocation.t.sol | 58 ------------------- .../test/staking/allocation/close.t.sol | 20 +++++++ .../test/staking/allocation/collect.t.sol | 32 ++++++++++ 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol index 266ec3c5b..3b1f0a56b 100644 --- a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol +++ b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol @@ -77,4 +77,10 @@ contract HorizonStakingExtensionTest is HorizonStakingTest { uint256 slot = 13; vm.store(address(staking), bytes32(slot), bytes32(MAX_ALLOCATION_EPOCHS) << 128); } + + function _storeRewardsDestination(address destination) internal { + uint256 rewardsDestinationSlot = 23; + bytes32 rewardsDestinationSlotBaseSlot = keccak256(abi.encode(users.indexer, rewardsDestinationSlot)); + vm.store(address(staking), rewardsDestinationSlotBaseSlot, bytes32(uint256(uint160(destination)))); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/allocation.t.sol b/packages/horizon/test/staking/allocation/allocation.t.sol index 1667c607c..feb89ec7c 100644 --- a/packages/horizon/test/staking/allocation/allocation.t.sol +++ b/packages/horizon/test/staking/allocation/allocation.t.sol @@ -53,62 +53,4 @@ contract HorizonStakingAllocationTest is HorizonStakingExtensionTest { bool isAllocation = staking.isAllocation(_allocationId); assertFalse(isAllocation); } - - function testCloseAllocation(uint256 tokens) public useIndexer { - tokens = bound(tokens, 1, MAX_STAKING_TOKENS); - _storeAllocation(tokens); - _storeMaxAllocationEpochs(); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); - - // Skip 15 epochs - vm.roll(15); - - staking.closeAllocation(_allocationId, _poi); - IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); - assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); - - // Stake should be updated with rewards - assertEq(staking.getStake(address(users.indexer)), tokens + ALLOCATIONS_REWARD_CUT); - } - - function testCloseAllocation_RevertWhen_NotActive() public { - vm.expectRevert("!active"); - staking.closeAllocation(_allocationId, _poi); - } - - function testCloseAllocation_RevertWhen_NotIndexer() public useAllocation { - resetPrank(users.delegator); - vm.expectRevert("!auth"); - staking.closeAllocation(_allocationId, _poi); - } - - function testCloseAllocation_AfterMaxEpochs_AnyoneCanClose(uint256 tokens) public useIndexer { - tokens = bound(tokens, 1, MAX_STAKING_TOKENS); - _storeAllocation(tokens); - _storeMaxAllocationEpochs(); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); - - // Skip to over the max allocation epochs - vm.roll(MAX_ALLOCATION_EPOCHS + 2); - - resetPrank(users.delegator); - staking.closeAllocation(_allocationId, 0x0); - IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); - assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); - - // No rewards distributed - assertEq(staking.getStake(address(users.indexer)), tokens); - } - - function testCloseAllocation_RevertWhen_ZeroTokensNotAuthorized() public useIndexer { - _storeAllocation(0); - _storeMaxAllocationEpochs(); - - // Skip to over the max allocation epochs - vm.roll(MAX_ALLOCATION_EPOCHS + 2); - - resetPrank(users.delegator); - vm.expectRevert("!auth"); - staking.closeAllocation(_allocationId, 0x0); - } } \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/close.t.sol b/packages/horizon/test/staking/allocation/close.t.sol index 21eb5a23e..0f15b84ea 100644 --- a/packages/horizon/test/staking/allocation/close.t.sol +++ b/packages/horizon/test/staking/allocation/close.t.sol @@ -29,6 +29,26 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { assertEq(staking.getStake(address(users.indexer)), tokens + ALLOCATIONS_REWARD_CUT); } + function testCloseAllocation_WithBeneficiaryAddress(uint256 tokens) public useIndexer { + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + _storeAllocation(tokens); + _storeMaxAllocationEpochs(); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + + address beneficiary = makeAddr("beneficiary"); + _storeRewardsDestination(beneficiary); + + // Skip 15 epochs + vm.roll(15); + + staking.closeAllocation(_allocationId, _poi); + IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); + assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); + + // Stake should be updated with rewards + assertEq(token.balanceOf(beneficiary), ALLOCATIONS_REWARD_CUT); + } + function testCloseAllocation_RevertWhen_NotActive() public { vm.expectRevert("!active"); staking.closeAllocation(_allocationId, _poi); diff --git a/packages/horizon/test/staking/allocation/collect.t.sol b/packages/horizon/test/staking/allocation/collect.t.sol index ea4d1abcf..ee33f89e5 100644 --- a/packages/horizon/test/staking/allocation/collect.t.sol +++ b/packages/horizon/test/staking/allocation/collect.t.sol @@ -150,4 +150,36 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { assertEq(curation.curation(_subgraphDeploymentID), curationTokens + curationCutTokens); assertEq(staking.getDelegationPool(users.indexer, subgraphDataServiceLegacyAddress).tokens, delegationTokens + delegationFeeCut); } + + function testCollect_WithBeneficiaryAddress( + uint256 provisionTokens, + uint256 allocationTokens, + uint256 collectTokens + ) public useIndexer useRebateParameters { + provisionTokens = bound(provisionTokens, 1, MAX_STAKING_TOKENS); + allocationTokens = bound(allocationTokens, 0, MAX_STAKING_TOKENS); + collectTokens = bound(collectTokens, 0, MAX_STAKING_TOKENS); + + _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); + _storeAllocation(allocationTokens); + + address beneficiary = makeAddr("beneficiary"); + _storeRewardsDestination(beneficiary); + + resetPrank(users.gateway); + approve(address(staking), collectTokens); + staking.collect(collectTokens, _allocationId); + + uint256 newRebates = ExponentialRebates.exponentialRebates( + collectTokens, + allocationTokens, + alphaNumerator, + alphaDenominator, + lambdaNumerator, + lambdaDenominator + ); + uint256 payment = newRebates > collectTokens ? collectTokens : newRebates; + + assertEq(token.balanceOf(beneficiary), payment); + } } \ No newline at end of file From 66f9767492fff45760d8d27e58e189eb4592d227 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 7 Jun 2024 18:19:53 -0300 Subject: [PATCH 117/277] chore: horizon close collection with delegation fees --- .../allocation/HorizonStakingExtension.t.sol | 11 ++++++++ .../test/staking/allocation/close.t.sol | 25 +++++++++++++++++++ .../test/staking/allocation/collect.t.sol | 10 +------- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol index 3b1f0a56b..19a42da2b 100644 --- a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol +++ b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol @@ -47,6 +47,17 @@ contract HorizonStakingExtensionTest is HorizonStakingTest { }); } + function _storeDelegationPool(uint256 tokens, uint32 indexingRewardCut, uint32 queryFeeCut) internal { + bytes32 baseSlot = keccak256(abi.encode(users.indexer, uint256(20))); + bytes32 feeCutValues = bytes32( + (uint256(indexingRewardCut) << uint256(32)) | + (uint256(queryFeeCut) << uint256(64)) + ); + bytes32 tokensSlot = bytes32(uint256(baseSlot) + 2); + vm.store(address(staking), baseSlot, feeCutValues); + vm.store(address(staking), tokensSlot, bytes32(tokens)); + } + /* * HELPERS */ diff --git a/packages/horizon/test/staking/allocation/close.t.sol b/packages/horizon/test/staking/allocation/close.t.sol index 0f15b84ea..d8524bb92 100644 --- a/packages/horizon/test/staking/allocation/close.t.sol +++ b/packages/horizon/test/staking/allocation/close.t.sol @@ -5,8 +5,10 @@ import "forge-std/Test.sol"; import { HorizonStakingExtensionTest } from "./HorizonStakingExtension.t.sol"; import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; +import { PPMMath } from "../../../contracts/libraries/PPMMath.sol"; contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { + using PPMMath for uint256; /* * TESTS @@ -89,4 +91,27 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { vm.expectRevert("!auth"); staking.closeAllocation(_allocationId, 0x0); } + + function testCloseAllocation_WithDelegation(uint256 tokens, uint256 delegationTokens, uint32 indexingRewardCut) public useIndexer { + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + vm.assume(indexingRewardCut <= MAX_PPM); + + _storeAllocation(tokens); + _storeMaxAllocationEpochs(); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + _storeDelegationPool(delegationTokens, indexingRewardCut, 0); + + // Skip 15 epochs + vm.roll(15); + + staking.closeAllocation(_allocationId, _poi); + IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); + assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); + + uint256 indexerRewardCut = ALLOCATIONS_REWARD_CUT.mulPPM(indexingRewardCut); + uint256 delegationFeeCut = ALLOCATIONS_REWARD_CUT - indexerRewardCut; + assertEq(staking.getStake(address(users.indexer)), tokens + indexerRewardCut); + assertEq(staking.getDelegationPool(users.indexer, subgraphDataServiceLegacyAddress).tokens, delegationTokens + delegationFeeCut); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/collect.t.sol b/packages/horizon/test/staking/allocation/collect.t.sol index ee33f89e5..b12783510 100644 --- a/packages/horizon/test/staking/allocation/collect.t.sol +++ b/packages/horizon/test/staking/allocation/collect.t.sol @@ -65,14 +65,6 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { vm.store(address(staking), slot, newProtocolTaxValue); } - function _storeDelegationPool(uint256 tokens, uint32 queryFeeCut) private { - bytes32 baseSlot = keccak256(abi.encode(users.indexer, uint256(20))); - bytes32 queryFeeCutValue = bytes32(uint256(queryFeeCut) << uint256(64)); - bytes32 tokensSlot = bytes32(uint256(baseSlot) + 2); - vm.store(address(staking), baseSlot, queryFeeCutValue); - vm.store(address(staking), tokensSlot, bytes32(tokens)); - } - /* * TESTS */ @@ -114,7 +106,7 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); _storeAllocation(allocationTokens); _storeProtocolTaxAndCuration(curationPercentage, protocolTaxPercentage); - _storeDelegationPool(delegationTokens, queryFeeCut); + _storeDelegationPool(delegationTokens, 0, queryFeeCut); curation.signal(_subgraphDeploymentID, curationTokens); resetPrank(users.gateway); From 99c273ee656027e49cb7f73c1477790698780402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Sat, 8 Jun 2024 00:09:56 +0200 Subject: [PATCH 118/277] fix: change delegation ratio to be a value instead of range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServiceFees.sol | 2 +- .../utilities/ProvisionManager.sol | 81 ++++++------------- .../utilities/ProvisionManagerStorage.sol | 10 +-- .../test/data-service/DataService.t.sol | 5 +- .../data-service/DataServiceUpgradeable.t.sol | 5 +- .../contracts/SubgraphService.sol | 14 ++-- .../contracts/interfaces/ISubgraphService.sol | 6 +- 7 files changed, 42 insertions(+), 81 deletions(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 1ffabce2c..d9a6122b6 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -39,7 +39,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat * @param _unlockTimestamp The timestamp when the tokens can be released */ function _lockStake(address _serviceProvider, uint256 _tokens, uint256 _unlockTimestamp) internal { - feesProvisionTracker.lock(_graphStaking(), _serviceProvider, _tokens, maximumDelegationRatio); + feesProvisionTracker.lock(_graphStaking(), _serviceProvider, _tokens, delegationRatio); LinkedList.List storage claimsList = claimsLists[_serviceProvider]; diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 247567bc2..a500febf9 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -17,7 +17,6 @@ import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; * if the parameter is out of range. * The parameters are: * - Provision parameters (thawing period and verifier cut) - * - Delegation ratio * - Provision tokens */ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionManagerV1Storage { @@ -31,11 +30,10 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa event ProvisionTokensRangeSet(uint256 min, uint256 max); /** - * @notice Emitted when the delegation ratio range is set. - * @param min The minimum allowed value for the delegation ratio. - * @param max The maximum allowed value for the delegation ratio. + * @notice Emitted when the delegation ratio is set. + * @param ratio The delegation ratio */ - event DelegationRatioRangeSet(uint32 min, uint32 max); + event DelegationRatioSet(uint32 ratio); /** * @notice Emitted when the verifier cut range is set. @@ -91,7 +89,6 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa modifier onlyValidProvision(address serviceProvider) virtual { IHorizonStaking.Provision memory provision = _getProvision(serviceProvider); _checkProvisionTokens(provision); - _checkProvisionDelegationRatio(provision, serviceProvider); _checkProvisionParameters(provision, false); _; } @@ -124,12 +121,11 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa } /** - * @notice External getter for the delegation ratio range - * @return Minimum delegation ratio allowed - * @return Maximum delegation ratio allowed + * @notice External getter for the delegation ratio + * @return The delegation ratio */ - function getDelegationRatioRange() external view returns (uint32, uint32) { - return _getDelegationRatioRange(); + function getDelegationRatio() external view returns (uint32) { + return _getDelegationRatio(); } /** @@ -147,7 +143,6 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa // solhint-disable-next-line func-name-mixedcase function __ProvisionManager_init_unchained() internal onlyInitializing { _setProvisionTokensRange(type(uint256).min, type(uint256).max); - _setDelegationRatioRange(type(uint32).min, type(uint32).max); _setVerifierCutRange(type(uint32).min, type(uint32).max); _setThawingPeriodRange(type(uint64).min, type(uint64).max); } @@ -167,6 +162,14 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa } // -- setters -- + /** + * @notice Sets the delegation ratio. + * @param _ratio The delegation ratio to be set + */ + function _setDelegationRatio(uint32 _ratio) internal { + delegationRatio = _ratio; + emit DelegationRatioSet(_ratio); + } /** * @notice Sets the range for the provision tokens. @@ -179,17 +182,6 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa emit ProvisionTokensRangeSet(_min, _max); } - /** - * @notice Sets the range for the delegation ratio. - * @param _min The minimum allowed value for the delegation ratio. - * @param _max The maximum allowed value for the delegation ratio. - */ - function _setDelegationRatioRange(uint32 _min, uint32 _max) internal { - minimumDelegationRatio = _min; - maximumDelegationRatio = _max; - emit DelegationRatioRangeSet(_min, _max); - } - /** * @notice Sets the range for the verifier cut. * @param _min The minimum allowed value for the max verifier cut. @@ -231,32 +223,6 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa _checkValueInRange(_provision.tokens, minimumProvisionTokens, maximumProvisionTokens, "tokens"); } - /** - * @notice Checks if the delegation ratio of a service provider is within the valid range. - * @param _serviceProvider The address of the service provider. - */ - function _checkProvisionDelegationRatio(address _serviceProvider) internal view virtual { - IHorizonStaking.Provision memory provision = _getProvision(_serviceProvider); - _checkProvisionDelegationRatio(provision, _serviceProvider); - } - - /** - * @notice Checks if the delegation ratio of a service provider is within the valid range. - * @param _provision The provision to check. - * @param _serviceProvider The address of the service provider. - */ - function _checkProvisionDelegationRatio( - IHorizonStaking.Provision memory _provision, - address _serviceProvider - ) internal view virtual { - (uint32 delegationRatioMin, uint32 delegationRatioMax) = _getDelegationRatioRange(); - if (delegationRatioMin == type(uint32).min && delegationRatioMax == type(uint32).max) return; - - uint256 delegatedTokens = _graphStaking().getDelegatedTokensAvailable(_serviceProvider, address(this)); - uint256 delegationRatioToCheck = uint32(delegatedTokens / (_provision.tokens - _provision.tokensThawing)); - _checkValueInRange(delegationRatioToCheck, delegationRatioMin, delegationRatioMax, "delegationRatio"); - } - /** * @notice Checks if the provision parameters of a service provider are within the valid range. * @param _serviceProvider The address of the service provider. @@ -291,6 +257,14 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa // -- getters -- + /** + * @notice Gets the delegation ratio. + * @return The delegation ratio + */ + function _getDelegationRatio() internal view virtual returns (uint32) { + return delegationRatio; + } + /** * @notice Gets the range for the provision tokens. * @return min The minimum allowed value for the provision tokens. @@ -300,15 +274,6 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa return (minimumProvisionTokens, maximumProvisionTokens); } - /** - * @notice Gets the range for the delegation ratio. - * @return min The minimum allowed value for the delegation ratio. - * @return max The maximum allowed value for the delegation ratio. - */ - function _getDelegationRatioRange() internal view virtual returns (uint32 min, uint32 max) { - return (minimumDelegationRatio, maximumDelegationRatio); - } - /** * @notice Gets the range for the thawing period. * @return min The minimum allowed value for the thawing period. diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index acc24d5a0..70f10d6e3 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -11,12 +11,6 @@ abstract contract ProvisionManagerV1Storage { /// @notice The maximum amount of tokens allowed to register a provision in the data service uint256 public maximumProvisionTokens; - /// @notice Minimum delegation to self stake ratio required - uint32 public minimumDelegationRatio; - - /// @notice Maximum delegation to self stake ratio allowed for a service provider - uint32 public maximumDelegationRatio; - /// @notice The minimum thawing period required to register a provision in the data service uint64 public minimumThawingPeriod; @@ -29,6 +23,10 @@ abstract contract ProvisionManagerV1Storage { /// @notice The maximum verifier cut allowed to register a provision in the data service uint32 public maximumVerifierCut; + /// @notice How much delegation the service provider can effectively use + /// @dev Max calculated as service provider's stake * delegationRatio + uint32 public delegationRatio; + /// @dev Gap to allow adding variables in future upgrades uint256[50] private __gap; } diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol index 738e2112d..66d12d80b 100644 --- a/packages/horizon/test/data-service/DataService.t.sol +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -8,9 +8,8 @@ contract DataServiceTest is GraphBaseTest { function test_WhenTheContractIsDeployedWithAValidController() external { DataServiceBase dataService = _deployDataService(); - (uint32 minDelegationRatio, uint32 maxDelegationRatio) = dataService.getDelegationRatioRange(); - assertEq(minDelegationRatio, type(uint32).min); - assertEq(maxDelegationRatio, type(uint32).max); + uint32 delegationRatio = dataService.getDelegationRatio(); + assertEq(delegationRatio, type(uint32).min); (uint256 minTokens, uint256 maxTokens) = dataService.getProvisionTokensRange(); assertEq(minTokens, type(uint256).min); diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol index 5523d7286..49ddec3d7 100644 --- a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol +++ b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol @@ -10,9 +10,8 @@ contract DataServiceUpgradeableTest is GraphBaseTest { function test_WhenTheContractIsDeployedWithAValidController() external { DataServiceBaseUpgradeable dataService = _deployDataService(); - (uint32 minDelegationRatio, uint32 maxDelegationRatio) = dataService.getDelegationRatioRange(); - assertEq(minDelegationRatio, type(uint32).min); - assertEq(maxDelegationRatio, type(uint32).max); + uint32 delegationRatio = dataService.getDelegationRatio(); + assertEq(delegationRatio, type(uint32).min); (uint256 minTokens, uint256 maxTokens) = dataService.getProvisionTokensRange(); assertEq(minTokens, type(uint256).min); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index e127abd3d..d45e13ba3 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -82,14 +82,14 @@ contract SubgraphService is * @dev The thawingPeriod and verifierCut ranges are not set here because they are variables * on the DisputeManager. We use the {ProvisionManager} overrideable getters to get the ranges. */ - function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external override initializer { + function initialize(uint256 minimumProvisionTokens, uint32 delegationRatio) external override initializer { __Ownable_init(msg.sender); __DataService_init(); __DataServicePausable_init(); __AllocationManager_init("SubgraphService", "1.0"); _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); - _setDelegationRatioRange(type(uint32).min, maximumDelegationRatio); + _setDelegationRatio(delegationRatio); } /** @@ -192,7 +192,7 @@ contract SubgraphService is data, (bytes32, uint256, address, bytes) ); - _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof, maximumDelegationRatio); + _allocate(indexer, allocationId, subgraphDeploymentId, tokens, allocationProof, delegationRatio); emit ServiceStarted(indexer, data); } @@ -297,7 +297,7 @@ contract SubgraphService is onlyRegisteredIndexer(indexer) whenNotPaused { - _resizeAllocation(allocationId, tokens, maximumDelegationRatio); + _resizeAllocation(allocationId, tokens, delegationRatio); } /** @@ -333,10 +333,10 @@ contract SubgraphService is } /** - * @notice See {ISubgraphService.setMaximumDelegationRatio} + * @notice See {ISubgraphService.setDelegationRatio} */ - function setMaximumDelegationRatio(uint32 maximumDelegationRatio) external override onlyOwner { - _setDelegationRatioRange(type(uint32).min, maximumDelegationRatio); + function setDelegationRatio(uint32 delegationRatio) external override onlyOwner { + _setDelegationRatio(delegationRatio); } /** diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index d4b51999b..39fc7430d 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -128,10 +128,10 @@ interface ISubgraphService is IDataServiceFees { function setMinimumProvisionTokens(uint256 minimumProvisionTokens) external; /** - * @notice Sets the maximum delegation ratio allowed for an allocation - * @param maximumDelegationRatio The maximum delegation ratio allowed for an allocation + * @notice Sets the delegation ratio + * @param delegationRatio The delegation ratio */ - function setMaximumDelegationRatio(uint32 maximumDelegationRatio) external; + function setDelegationRatio(uint32 delegationRatio) external; /** * @notice Sets the rewards destination for an indexer to receive indexing rewards From 1741ea2311b009d11005075369729246abd448e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Sat, 8 Jun 2024 00:24:12 +0200 Subject: [PATCH 119/277] fix: moar feedback fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/IBridgeEscrow.sol | 26 ------------------- .../contracts/libraries/Denominations.sol | 1 + .../contracts/utilities/GraphDirectory.sol | 15 ----------- packages/horizon/eslint.config.js | 2 +- packages/horizon/package.json | 2 +- packages/horizon/test/GraphBase.t.sol | 1 - .../test/utilities/GraphDirectory.t.sol | 2 -- .../GraphDirectoryImplementation.sol | 5 ---- packages/subgraph-service/package.json | 2 +- 9 files changed, 4 insertions(+), 52 deletions(-) delete mode 100644 packages/horizon/contracts/interfaces/IBridgeEscrow.sol diff --git a/packages/horizon/contracts/interfaces/IBridgeEscrow.sol b/packages/horizon/contracts/interfaces/IBridgeEscrow.sol deleted file mode 100644 index 4e0021423..000000000 --- a/packages/horizon/contracts/interfaces/IBridgeEscrow.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -pragma solidity 0.8.26; - -/** - * @title IBridgeEscrow - */ -interface IBridgeEscrow { - /** - * @notice Initialize the BridgeEscrow contract. - * @param controller Address of the Controller that manages this contract - */ - function initialize(address controller) external; - - /** - * @notice Approve a spender (i.e. a bridge that manages the GRT funds held by the escrow) - * @param spender Address of the spender that will be approved - */ - function approveAll(address spender) external; - - /** - * @notice Revoke a spender (i.e. a bridge that will no longer manage the GRT funds held by the escrow) - * @param spender Address of the spender that will be revoked - */ - function revokeAll(address spender) external; -} diff --git a/packages/horizon/contracts/libraries/Denominations.sol b/packages/horizon/contracts/libraries/Denominations.sol index ae3adab94..fe5cf2d05 100644 --- a/packages/horizon/contracts/libraries/Denominations.sol +++ b/packages/horizon/contracts/libraries/Denominations.sol @@ -8,6 +8,7 @@ pragma solidity 0.8.26; */ library Denominations { /// @notice The address of the native token, i.e ETH + /// @dev This convention is taken from https://eips.ethereum.org/EIPS/eip-7528 address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /** diff --git a/packages/horizon/contracts/utilities/GraphDirectory.sol b/packages/horizon/contracts/utilities/GraphDirectory.sol index 570a5d476..b63bcdeab 100644 --- a/packages/horizon/contracts/utilities/GraphDirectory.sol +++ b/packages/horizon/contracts/utilities/GraphDirectory.sol @@ -11,7 +11,6 @@ import { IController } from "@graphprotocol/contracts/contracts/governance/ICont import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; import { ITokenGateway } from "@graphprotocol/contracts/contracts/arbitrum/ITokenGateway.sol"; -import { IBridgeEscrow } from "../interfaces/IBridgeEscrow.sol"; import { IGraphProxyAdmin } from "../interfaces/IGraphProxyAdmin.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; @@ -52,9 +51,6 @@ abstract contract GraphDirectory { /// @notice The Token Gateway contract address ITokenGateway private immutable GRAPH_TOKEN_GATEWAY; - /// @notice The Bridge Escrow contract address - IBridgeEscrow private immutable GRAPH_BRIDGE_ESCROW; - /// @notice The Graph Proxy Admin contract address IGraphProxyAdmin private immutable GRAPH_PROXY_ADMIN; @@ -73,7 +69,6 @@ abstract contract GraphDirectory { * @param graphEpochManager The Epoch Manager contract address * @param graphRewardsManager The Rewards Manager contract address * @param graphTokenGateway The Token Gateway contract address - * @param graphBridgeEscrow The Bridge Escrow contract address * @param graphProxyAdmin The Graph Proxy Admin contract address * @param graphCuration The Curation contract address */ @@ -86,7 +81,6 @@ abstract contract GraphDirectory { address graphEpochManager, address graphRewardsManager, address graphTokenGateway, - address graphBridgeEscrow, address graphProxyAdmin, address graphCuration ); @@ -118,7 +112,6 @@ abstract contract GraphDirectory { GRAPH_EPOCH_MANAGER = IEpochManager(_getContractFromController("EpochManager")); GRAPH_REWARDS_MANAGER = IRewardsManager(_getContractFromController("RewardsManager")); GRAPH_TOKEN_GATEWAY = ITokenGateway(_getContractFromController("GraphTokenGateway")); - GRAPH_BRIDGE_ESCROW = IBridgeEscrow(_getContractFromController("BridgeEscrow")); GRAPH_PROXY_ADMIN = IGraphProxyAdmin(_getContractFromController("GraphProxyAdmin")); GRAPH_CURATION = ICuration(_getContractFromController("Curation")); @@ -131,7 +124,6 @@ abstract contract GraphDirectory { address(GRAPH_EPOCH_MANAGER), address(GRAPH_REWARDS_MANAGER), address(GRAPH_TOKEN_GATEWAY), - address(GRAPH_BRIDGE_ESCROW), address(GRAPH_PROXY_ADMIN), address(GRAPH_CURATION) ); @@ -193,13 +185,6 @@ abstract contract GraphDirectory { return GRAPH_TOKEN_GATEWAY; } - /** - * @notice Get the Bridge Escrow contract - */ - function _graphBridgeEscrow() internal view returns (IBridgeEscrow) { - return GRAPH_BRIDGE_ESCROW; - } - /** * @notice Get the Graph Proxy Admin contract */ diff --git a/packages/horizon/eslint.config.js b/packages/horizon/eslint.config.js index 2cb4335fd..c9e06b116 100644 --- a/packages/horizon/eslint.config.js +++ b/packages/horizon/eslint.config.js @@ -16,6 +16,6 @@ module.exports = [ }, }, { - ignores: ['typechain-types/*'], + ignores: ['typechain-types/*', 'lib/*'], }, ] diff --git a/packages/horizon/package.json b/packages/horizon/package.json index e6001d96c..a214e1d0a 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -2,7 +2,7 @@ "name": "@graphprotocol/horizon", "version": "0.0.1", "description": "", - "author": "The Graph Team", + "author": "The Graph core devs", "license": "GPL-2.0-or-later", "scripts": { "lint:ts": "eslint '**/*.{js,ts}' --fix", diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index c7f57197a..b978fba2d 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -142,7 +142,6 @@ abstract contract GraphBaseTest is Utils, Constants { controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); controller.setContractProxy(keccak256("Curation"), address(curation)); controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); - controller.setContractProxy(keccak256("BridgeEscrow"), makeAddr("BridgeEscrow")); controller.setContractProxy(keccak256("GraphProxyAdmin"), address(proxyAdmin)); resetPrank(users.deployer); diff --git a/packages/horizon/test/utilities/GraphDirectory.t.sol b/packages/horizon/test/utilities/GraphDirectory.t.sol index 6a2c958b8..35ab2a291 100644 --- a/packages/horizon/test/utilities/GraphDirectory.t.sol +++ b/packages/horizon/test/utilities/GraphDirectory.t.sol @@ -19,7 +19,6 @@ contract GraphDirectoryTest is GraphBaseTest { _getContractFromController("EpochManager"), _getContractFromController("RewardsManager"), _getContractFromController("GraphTokenGateway"), - _getContractFromController("BridgeEscrow"), _getContractFromController("GraphProxyAdmin"), _getContractFromController("Curation") ); @@ -49,7 +48,6 @@ contract GraphDirectoryTest is GraphBaseTest { assertEq(_getContractFromController("EpochManager"), address(directory.graphEpochManager())); assertEq(_getContractFromController("RewardsManager"), address(directory.graphRewardsManager())); assertEq(_getContractFromController("GraphTokenGateway"), address(directory.graphTokenGateway())); - assertEq(_getContractFromController("BridgeEscrow"), address(directory.graphBridgeEscrow())); assertEq(_getContractFromController("GraphProxyAdmin"), address(directory.graphProxyAdmin())); assertEq(_getContractFromController("Curation"), address(directory.graphCuration())); } diff --git a/packages/horizon/test/utilities/GraphDirectoryImplementation.sol b/packages/horizon/test/utilities/GraphDirectoryImplementation.sol index 9f4b5066c..57780f450 100644 --- a/packages/horizon/test/utilities/GraphDirectoryImplementation.sol +++ b/packages/horizon/test/utilities/GraphDirectoryImplementation.sol @@ -11,7 +11,6 @@ import { IController } from "@graphprotocol/contracts/contracts/governance/ICont import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; import { ITokenGateway } from "@graphprotocol/contracts/contracts/arbitrum/ITokenGateway.sol"; -import { IBridgeEscrow } from "../../contracts/interfaces/IBridgeEscrow.sol"; import { IGraphProxyAdmin } from "../../contracts/interfaces/IGraphProxyAdmin.sol"; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; @@ -55,10 +54,6 @@ contract GraphDirectoryImplementation is GraphDirectory { return _graphTokenGateway(); } - function graphBridgeEscrow() external view returns (IBridgeEscrow) { - return _graphBridgeEscrow(); - } - function graphProxyAdmin() external view returns (IGraphProxyAdmin) { return _graphProxyAdmin(); } diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index b591a4d41..a90790742 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -2,7 +2,7 @@ "name": "@graphprotocol/subgraph-service", "version": "0.0.1", "description": "", - "author": "The Graph Team", + "author": "The Graph core devs", "license": "GPL-2.0-or-later", "scripts": { "lint:ts": "eslint '**/*.{js,ts}' --fix", From 6f376cd2e64c14507707e801992c8c19e76a3aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 7 Jun 2024 19:25:19 -0300 Subject: [PATCH 120/277] =?UTF-8?q?fix:=20ensure=20rewards=20manager=20loo?= =?UTF-8?q?ks=20at=20subgraph=20service=20and=20staking=20for=E2=80=A6=20(?= =?UTF-8?q?#982)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: ensure rewards manager looks at subgraph service and staking for allos Signed-off-by: Tomás Migone * fix: typo Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone --- .../contracts/rewards/IRewardsIssuer.sol | 20 ++++++- .../contracts/rewards/IRewardsManager.sol | 2 +- .../contracts/rewards/RewardsManager.sol | 59 +++++++++++++++---- .../rewards/RewardsManagerStorage.sol | 7 ++- .../contracts/staking/IStakingBase.sol | 14 +++++ .../contracts/contracts/staking/Staking.sol | 21 +++++++ .../test/unit/rewards/rewards.test.ts | 10 ++-- .../internal/IHorizonStakingExtension.sol | 7 --- .../staking/HorizonStakingExtension.sol | 9 +++ .../contracts/SubgraphService.sol | 24 ++++++++ .../test/mocks/MockRewardsManager.sol | 2 +- 11 files changed, 141 insertions(+), 34 deletions(-) diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol index 21dcc8768..949c564a2 100644 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -5,9 +5,9 @@ pragma solidity ^0.7.6 || 0.8.26; interface IRewardsIssuer { /** * @dev Get allocation data to calculate rewards issuance - * @param allocationId The allocation ID + * @param allocationId The allocation Id * @return indexer The indexer address - * @return subgraphDeploymentID Subgraph deployment id for the allocation + * @return subgraphDeploymentId Subgraph deployment id for the allocation * @return tokens Amount of allocated tokens * @return accRewardsPerAllocatedToken Rewards snapshot */ @@ -16,5 +16,19 @@ interface IRewardsIssuer { ) external view - returns (address indexer, bytes32 subgraphDeploymentID, uint256 tokens, uint256 accRewardsPerAllocatedToken); + returns (address indexer, bytes32 subgraphDeploymentId, uint256 tokens, uint256 accRewardsPerAllocatedToken); + + /** + * @notice Return the total amount of tokens allocated to subgraph. + * @param _subgraphDeploymentId Deployment Id for the subgraph + * @return Total tokens allocated to subgraph + */ + function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentId) external view returns (uint256); + + /** + * @notice Wether or not an allocation is active (i.e open) + * @param _allocationId Allocation Id + * @return Wether or not the allocation is active + */ + function isActiveAllocation(address _allocationId) external view returns (bool); } diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index 1602fe91e..e511748e3 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -19,7 +19,7 @@ interface IRewardsManager { function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external; - function setRewardsIssuer(address _rewardsIssuer, bool _allowed) external; + function setSubgraphService(address _subgraphService) external; // -- Denylist -- diff --git a/packages/contracts/contracts/rewards/RewardsManager.sol b/packages/contracts/contracts/rewards/RewardsManager.sol index 41c79e861..21512ec80 100644 --- a/packages/contracts/contracts/rewards/RewardsManager.sol +++ b/packages/contracts/contracts/rewards/RewardsManager.sol @@ -52,9 +52,9 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa event RewardsDenylistUpdated(bytes32 indexed subgraphDeploymentID, uint256 sinceBlock); /** - * @dev Emitted when a rewards issuer is updated. + * @dev Emitted when the subgraph service is set */ - event RewardsIssuerSet(address indexed rewardsIssuer, bool allowed); + event SubgraphServiceSet(address indexed oldSubgraphService, address indexed newSubgraphService); // -- Modifiers -- @@ -121,9 +121,10 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa emit ParameterUpdated("minimumSubgraphSignal"); } - function setRewardsIssuer(address _rewardsIssuer, bool _allowed) external override onlyGovernor { - rewardsIssuers[_rewardsIssuer] = _allowed; - emit RewardsIssuerSet(_rewardsIssuer, _allowed); + function setSubgraphService(address _subgraphService) external override onlyGovernor { + address oldSubgraphService = address(subgraphService); + subgraphService = IRewardsIssuer(_subgraphService); + emit SubgraphServiceSet(oldSubgraphService, _subgraphService); } // -- Denylist -- @@ -258,7 +259,19 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa subgraph.accRewardsForSubgraphSnapshot ); - uint256 subgraphAllocatedTokens = staking().getSubgraphAllocatedTokens(_subgraphDeploymentID); + // There are two contributors to subgraph allocated tokens: + // - the legacy allocations on the legacy staking contract + // - the new allocations on the subgraph service + uint256 subgraphAllocatedTokens = 0; + address[2] memory rewardsIssuers = [address(staking()), address(subgraphService)]; + for (uint256 i = 0; i < rewardsIssuers.length; i++) { + if (rewardsIssuers[i] != address(0)) { + subgraphAllocatedTokens += IRewardsIssuer(rewardsIssuers[i]).getSubgraphAllocatedTokens( + _subgraphDeploymentID + ); + } + } + if (subgraphAllocatedTokens == 0) { return (0, accRewardsForSubgraph); } @@ -321,19 +334,35 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa /** * @dev Calculate current rewards for a given allocation on demand. + * The allocation could be a legacy allocation or a new subgraph service allocation. * @param _allocationID Allocation * @return Rewards amount for an allocation */ function getRewards(address _allocationID) external view override returns (uint256) { - IStaking.AllocationState allocState = staking().getAllocationState(_allocationID); - if (allocState != IStakingBase.AllocationState.Active) { + address rewardsIssuer = address(0); + + // Check both the legacy and new allocations + address[2] memory rewardsIssuers = [address(staking()), address(subgraphService)]; + for (uint256 i = 0; i < rewardsIssuers.length; i++) { + if (rewardsIssuers[i] != address(0)) { + if (IRewardsIssuer(rewardsIssuers[i]).isActiveAllocation(_allocationID)) { + rewardsIssuer = address(rewardsIssuers[i]); + break; + } + } + } + + // Bail if allo does not exist + if (rewardsIssuer == address(0)) { return 0; } - IStaking.Allocation memory alloc = staking().getAllocation(_allocationID); + (, bytes32 subgraphDeploymentId, uint256 tokens, uint256 alloAccRewardsPerAllocatedToken) = IRewardsIssuer( + rewardsIssuer + ).getAllocationData(_allocationID); - (uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken(alloc.subgraphDeploymentID); - return _calcRewards(alloc.tokens, alloc.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken); + (uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken(subgraphDeploymentId); + return _calcRewards(tokens, alloAccRewardsPerAllocatedToken, accRewardsPerAllocatedToken); } /** @@ -354,14 +383,18 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa /** * @dev Pull rewards from the contract for a particular allocation. - * This function can only be called by the Staking contract. + * This function can only be called by an authorized rewards issuer which are + * the staking contract (for legacy allocations), and the subgraph service (for new allocations). * This function will mint the necessary tokens to reward based on the inflation calculation. * @param _allocationID Allocation * @return Assigned rewards amount */ function takeRewards(address _allocationID) external override returns (uint256) { address rewardsIssuer = msg.sender; - require(rewardsIssuers[rewardsIssuer], "Caller must be a rewards issuer"); + require( + rewardsIssuer == address(staking()) || rewardsIssuer == address(subgraphService), + "Caller must be a rewards issuer" + ); ( address indexer, diff --git a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol index afcd98e43..c40ad38f4 100644 --- a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol +++ b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6; +pragma solidity ^0.7.6 || 0.8.26; import "./IRewardsManager.sol"; import "../governance/Managed.sol"; +import { IRewardsIssuer } from "./IRewardsIssuer.sol"; contract RewardsManagerV1Storage is Managed { // -- State -- @@ -38,6 +39,6 @@ contract RewardsManagerV4Storage is RewardsManagerV3Storage { } contract RewardsManagerV5Storage is RewardsManagerV4Storage { - // List of addresses that are allowed to issue rewards - mapping(address => bool) public rewardsIssuers; + // Address of the subgraph service + IRewardsIssuer public subgraphService; } diff --git a/packages/contracts/contracts/staking/IStakingBase.sol b/packages/contracts/contracts/staking/IStakingBase.sol index b30d00499..6ca3957f4 100644 --- a/packages/contracts/contracts/staking/IStakingBase.sol +++ b/packages/contracts/contracts/staking/IStakingBase.sol @@ -361,6 +361,20 @@ interface IStakingBase is IStakingData { */ function getAllocation(address _allocationID) external view returns (Allocation memory); + /** + * @dev New function to get the allocation data for the rewards manager + * @dev Note that this is only to make tests pass, as the staking contract with + * this changes will never get deployed. HorizonStaking is taking it's place. + */ + function getAllocationData(address _allocationID) external view returns (address, bytes32, uint256, uint256); + + /** + * @dev New function to get the allocation active status for the rewards manager + * @dev Note that this is only to make tests pass, as the staking contract with + * this changes will never get deployed. HorizonStaking is taking it's place. + */ + function isActiveAllocation(address _allocationID) external view returns (bool); + /** * @notice Return the current state of an allocation * @param _allocationID Allocation identifier diff --git a/packages/contracts/contracts/staking/Staking.sol b/packages/contracts/contracts/staking/Staking.sol index e9da34440..83745c30a 100644 --- a/packages/contracts/contracts/staking/Staking.sol +++ b/packages/contracts/contracts/staking/Staking.sol @@ -472,6 +472,27 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M return __allocations[_allocationID]; } + /** + * @dev New function to get the allocation data for the rewards manager + * @dev Note that this is only to make tests pass, as the staking contract with + * this changes will never get deployed. HorizonStaking is taking it's place. + */ + function getAllocationData( + address _allocationID + ) external view override returns (address, bytes32, uint256, uint256) { + Allocation memory alloc = __allocations[_allocationID]; + return (alloc.indexer, alloc.subgraphDeploymentID, alloc.tokens, alloc.accRewardsPerAllocatedToken); + } + + /** + * @dev New function to get the allocation active status for the rewards manager + * @dev Note that this is only to make tests pass, as the staking contract with + * this changes will never get deployed. HorizonStaking is taking it's place. + */ + function isActiveAllocation(address _allocationID) external view override returns (bool) { + return _getAllocationState(_allocationID) == AllocationState.Active; + } + /** * @notice Return the current state of an allocation * @param _allocationID Allocation identifier diff --git a/packages/contracts/test/unit/rewards/rewards.test.ts b/packages/contracts/test/unit/rewards/rewards.test.ts index 1070b9ff3..c9e0f6a28 100644 --- a/packages/contracts/test/unit/rewards/rewards.test.ts +++ b/packages/contracts/test/unit/rewards/rewards.test.ts @@ -653,7 +653,6 @@ describe('Rewards', () => { const event = rewardsManager.interface.parseLog(receipt.logs[1]).args expect(event.indexer).eq(indexer1.address) expect(event.allocationID).eq(allocationID1) - expect(event.epoch).eq(await epochManager.currentEpoch()) expect(toRound(event.amount)).eq(toRound(expectedIndexingRewards)) // After state @@ -692,7 +691,7 @@ describe('Rewards', () => { const tx = staking.connect(indexer1).closeAllocation(allocationID1, randomHexBytes()) await expect(tx) .emit(rewardsManager, 'RewardsAssigned') - .withArgs(indexer1.address, allocationID1, await epochManager.currentEpoch(), toBN(0)) + .withArgs(indexer1.address, allocationID1, toBN(0)) }) it('does not revert with an underflow if the minimum signal changes, and signal came after allocation', async function () { @@ -710,7 +709,7 @@ describe('Rewards', () => { const tx = staking.connect(indexer1).closeAllocation(allocationID1, randomHexBytes()) await expect(tx) .emit(rewardsManager, 'RewardsAssigned') - .withArgs(indexer1.address, allocationID1, await epochManager.currentEpoch(), toBN(0)) + .withArgs(indexer1.address, allocationID1, toBN(0)) }) it('does not revert if signal was already under minimum', async function () { @@ -727,7 +726,7 @@ describe('Rewards', () => { await expect(tx) .emit(rewardsManager, 'RewardsAssigned') - .withArgs(indexer1.address, allocationID1, await epochManager.currentEpoch(), toBN(0)) + .withArgs(indexer1.address, allocationID1, toBN(0)) }) it('should distribute rewards on closed allocation and send to destination', async function () { @@ -761,7 +760,6 @@ describe('Rewards', () => { const event = rewardsManager.interface.parseLog(receipt.logs[1]).args expect(event.indexer).eq(indexer1.address) expect(event.allocationID).eq(allocationID1) - expect(event.epoch).eq(await epochManager.currentEpoch()) expect(toRound(event.amount)).eq(toRound(expectedIndexingRewards)) // After state @@ -853,7 +851,7 @@ describe('Rewards', () => { const tx = staking.connect(indexer1).closeAllocation(allocationID1, randomHexBytes()) await expect(tx) .emit(rewardsManager, 'RewardsDenied') - .withArgs(indexer1.address, allocationID1, await epochManager.currentEpoch()) + .withArgs(indexer1.address, allocationID1) }) }) }) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 3c9a26c91..d0331580e 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -160,13 +160,6 @@ interface IHorizonStakingExtension is IRewardsIssuer { */ function isAllocation(address allocationID) external view returns (bool); - /** - * @notice Return the total amount of tokens allocated to subgraph. - * @param subgraphDeploymentID Deployment ID for the subgraph - * @return Total tokens allocated to subgraph - */ - function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentID) external view returns (uint256); - /** * @notice Retrun the time in blocks to unstake * @return Thawing period in blocks diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 7abac7623..7931c2988 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -267,6 +267,15 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon return __DEPRECATED_subgraphAllocations[subgraphDeploymentID]; } + /** + * @notice Return true if allocation is active. + * @param allocationID Allocation identifier + * @return True if allocation is active + */ + function isActiveAllocation(address allocationID) external view override returns (bool) { + return _getAllocationState(allocationID) == AllocationState.Active; + } + /** * @notice Get the total amount of tokens staked by the indexer. * @param indexer Address of the indexer diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index d45e13ba3..566394b51 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -33,6 +33,7 @@ contract SubgraphService is { using PPMMath for uint256; using Allocation for mapping(address => Allocation.State); + using Allocation for Allocation.State; /** * @notice Checks that an indexer is registered @@ -372,6 +373,29 @@ contract SubgraphService is ); } + /** + * @notice Return the total amount of tokens allocated to subgraph. + * @dev Implements {IRewardsIssuer.getSubgraphAllocatedTokens} + * @dev To be used by the {RewardsManager}. + * @param subgraphDeploymentId Deployment Id for the subgraph + * @return Total tokens allocated to subgraph + */ + function getSubgraphAllocatedTokens(bytes32 subgraphDeploymentId) external view override returns (uint256) { + return subgraphAllocatedTokens[subgraphDeploymentId]; + } + + /** + * @notice Check if an allocation is open + * @dev Implements {IRewardsIssuer.isAllocationActive} + * @dev To be used by the {RewardsManager}. + * + * @param allocationId The allocation Id + * @return Wether or not the allocation is active + */ + function isActiveAllocation(address allocationId) external view override returns (bool) { + return allocations[allocationId].isOpen(); + } + /** * @notice See {ISubgraphService.getLegacyAllocation} */ diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index 3e43e8109..158feef50 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -12,7 +12,7 @@ contract MockRewardsManager is IRewardsManager { function setMinimumSubgraphSignal(uint256) external {} - function setRewardsIssuer(address, bool) external {} + function setSubgraphService(address) external {} // -- Denylist -- From 02a2fc3e37334c89a6b44acfdcd9bd023333655c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Sat, 8 Jun 2024 01:16:06 +0200 Subject: [PATCH 121/277] feat: use poi to create dispute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/DisputeManager.sol | 20 ++++++++---- .../contracts/interfaces/IDisputeManager.sol | 5 +-- packages/subgraph-service/package.json | 2 +- .../test/DisputeManager.t.sol | 31 ++++++++++++------- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 692c6a93c..b1d894061 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -119,18 +119,24 @@ contract DisputeManager is /** * @notice Create an indexing dispute for the arbitrator to resolve. - * The disputes are created in reference to an allocationId + * The disputes are created in reference to an allocationId and specifically + * a POI for that allocation. * This function is called by a challenger that will need to `_deposit` at * least `minimumDeposit` GRT tokens. * @param allocationId The allocation to dispute + * @param poi The Proof of Indexing (POI) being disputed * @param deposit Amount of tokens staked as deposit */ - function createIndexingDispute(address allocationId, uint256 deposit) external override returns (bytes32) { + function createIndexingDispute( + address allocationId, + bytes32 poi, + uint256 deposit + ) external override returns (bytes32) { // Get funds from submitter _pullSubmitterDeposit(deposit); // Create a dispute - return _createIndexingDisputeWithAllocation(msg.sender, deposit, allocationId); + return _createIndexingDisputeWithAllocation(msg.sender, deposit, allocationId, poi); } /** @@ -486,14 +492,16 @@ contract DisputeManager is * @param _fisherman The challenger creating the dispute * @param _deposit Amount of tokens staked as deposit * @param _allocationId Allocation disputed + * @param _poi The POI being disputed */ function _createIndexingDisputeWithAllocation( address _fisherman, uint256 _deposit, - address _allocationId + address _allocationId, + bytes32 _poi ) private returns (bytes32) { // Create a disputeId - bytes32 disputeId = keccak256(abi.encodePacked(_allocationId)); + bytes32 disputeId = keccak256(abi.encodePacked(_allocationId, _poi)); // Only one dispute for an allocationId at a time require(!isDisputeCreated(disputeId), DisputeManagerDisputeAlreadyCreated(disputeId)); @@ -518,7 +526,7 @@ contract DisputeManager is block.timestamp ); - emit IndexingDisputeCreated(disputeId, alloc.indexer, _fisherman, _deposit, _allocationId); + emit IndexingDisputeCreated(disputeId, alloc.indexer, _fisherman, _deposit, _allocationId, _poi); return disputeId; } diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index f53b0f538..86b7783d8 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -100,7 +100,8 @@ interface IDisputeManager { address indexed indexer, address indexed fisherman, uint256 tokens, - address allocationId + address allocationId, + bytes32 poi ); /** @@ -193,7 +194,7 @@ interface IDisputeManager { bytes calldata attestationData2 ) external returns (bytes32, bytes32); - function createIndexingDispute(address allocationId, uint256 deposit) external returns (bytes32); + function createIndexingDispute(address allocationId, bytes32 poi, uint256 deposit) external returns (bytes32); function acceptDispute(bytes32 disputeId, uint256 tokensSlash) external; diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index a90790742..da7b33a3d 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -10,7 +10,7 @@ "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", "build": "forge build && hardhat compile", - "test": "FOUNDRY_PROFILE=lite forge test -vvv && hardhat test" + "test": "FOUNDRY_PROFILE=lite forge test -vvvv && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol index f11f0a051..97fd7b5ff 100644 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -6,6 +6,7 @@ import "forge-std/Test.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; +import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; import { DisputeManager } from "../contracts/DisputeManager.sol"; import { IDisputeManager } from "../contracts/interfaces/IDisputeManager.sol"; @@ -72,16 +73,24 @@ contract DisputeManagerTest is Test { controller.setContractProxy(keccak256("GraphToken"), address(graphToken)); controller.setContractProxy(keccak256("Staking"), address(staking)); controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); + controller.setContractProxy(keccak256("GraphPayments"), address(0x100)); + controller.setContractProxy(keccak256("PaymentsEscrow"), address(0x101)); + controller.setContractProxy(keccak256("EpochManager"), address(0x102)); + controller.setContractProxy(keccak256("GraphTokenGateway"), address(0x103)); + controller.setContractProxy(keccak256("GraphProxyAdmin"), address(0x104)); + controller.setContractProxy(keccak256("Curation"), address(0x105)); vm.stopPrank(); - disputeManager = new DisputeManager(address(controller)); - disputeManager.initialize( - arbitrator, - disputePeriod, - minimumDeposit, - fishermanRewardPercentage, - maxSlashingPercentage + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + address disputeManagerProxy = UnsafeUpgrades.deployTransparentProxy( + disputeManagerImplementation, + governor, + abi.encodeCall( + DisputeManager.initialize, + (arbitrator, disputePeriod, minimumDeposit, fishermanRewardPercentage, maxSlashingPercentage) + ) ); + disputeManager = DisputeManager(disputeManagerProxy); subgraphService = new SubgraphService(address(controller), address(disputeManager), tapVerifier, curation); subgraphService.initialize(1000 ether, 16); @@ -110,7 +119,7 @@ contract DisputeManagerTest is Test { vm.startPrank(fisherman); graphToken.mint(fisherman, tokens); graphToken.approve(address(disputeManager), tokens); - bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, tokens); + bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, bytes32("POI1234"), tokens); vm.stopPrank(); return _disputeID; } @@ -218,7 +227,7 @@ contract DisputeManagerTest is Test { graphToken.approve(address(disputeManager), tokens); bytes memory expectedError = abi.encodeWithSignature("DisputeManagerDisputeAlreadyCreated(bytes32)", disputeID); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, tokens); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1234"), tokens); vm.stopPrank(); } @@ -232,7 +241,7 @@ contract DisputeManagerTest is Test { 100 ether ); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, 50 ether); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1234"), 50 ether); vm.stopPrank(); } @@ -244,7 +253,7 @@ contract DisputeManagerTest is Test { graphToken.approve(address(disputeManager), tokens); bytes memory expectedError = abi.encodeWithSignature("DisputeManagerIndexerNotFound(address)", allocationID); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, tokens); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1234"), tokens); vm.stopPrank(); } From aba7ac591ceda1a68d15e3c57068b4a8d620b0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Sat, 8 Jun 2024 01:43:02 +0200 Subject: [PATCH 122/277] feat: use poi to create dispute id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .gitmodules | 3 ++ .../contracts/SubgraphService.sol | 2 +- .../lib/openzeppelin-foundry-upgrades | 1 + packages/subgraph-service/remappings.txt | 1 + .../test/DisputeManager.t.sol | 43 +++++++++++-------- .../test/mocks/MockHorizonStaking.sol | 10 ++++- 6 files changed, 40 insertions(+), 20 deletions(-) create mode 160000 packages/subgraph-service/lib/openzeppelin-foundry-upgrades diff --git a/.gitmodules b/.gitmodules index 313d1d2d0..8cd5a0672 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "packages/horizon/lib/openzeppelin-foundry-upgrades"] path = packages/horizon/lib/openzeppelin-foundry-upgrades url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades +[submodule "packages/subgraph-service/lib/openzeppelin-foundry-upgrades"] + path = packages/subgraph-service/lib/openzeppelin-foundry-upgrades + url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 566394b51..bd36002a0 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -74,7 +74,7 @@ contract SubgraphService is address disputeManager, address tapCollector, address curation - ) DataService(graphController) Directory(address(this), tapCollector, disputeManager, curation) { + ) DataService(graphController) Directory(address(this), disputeManager, tapCollector, curation) { _disableInitializers(); } diff --git a/packages/subgraph-service/lib/openzeppelin-foundry-upgrades b/packages/subgraph-service/lib/openzeppelin-foundry-upgrades new file mode 160000 index 000000000..4cd15fc50 --- /dev/null +++ b/packages/subgraph-service/lib/openzeppelin-foundry-upgrades @@ -0,0 +1 @@ +Subproject commit 4cd15fc50b141c77d8cc9ff8efb44d00e841a299 diff --git a/packages/subgraph-service/remappings.txt b/packages/subgraph-service/remappings.txt index 485676dc2..d5c1ff26c 100644 --- a/packages/subgraph-service/remappings.txt +++ b/packages/subgraph-service/remappings.txt @@ -6,3 +6,4 @@ eth-gas-reporter/=node_modules/eth-gas-reporter/ hardhat/=node_modules/hardhat/ @openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ +openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src \ No newline at end of file diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol index 97fd7b5ff..a5375dc0d 100644 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ b/packages/subgraph-service/test/DisputeManager.t.sol @@ -92,8 +92,15 @@ contract DisputeManagerTest is Test { ); disputeManager = DisputeManager(disputeManagerProxy); - subgraphService = new SubgraphService(address(controller), address(disputeManager), tapVerifier, curation); - subgraphService.initialize(1000 ether, 16); + address subgraphServiceImplementation = address( + new SubgraphService(address(controller), address(disputeManager), tapVerifier, curation) + ); + address subgraphServiceProxy = UnsafeUpgrades.deployTransparentProxy( + subgraphServiceImplementation, + governor, + abi.encodeCall(SubgraphService.initialize, (1000 ether, 16)) + ); + subgraphService = SubgraphService(subgraphServiceProxy); disputeManager.setSubgraphService(address(subgraphService)); } @@ -108,18 +115,18 @@ contract DisputeManagerTest is Test { bytes32 digest = subgraphService.encodeAllocationProof(indexer, _allocationID); (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - subgraphService.register(indexer, abi.encode("url", "geoHash")); + subgraphService.register(indexer, abi.encode("url", "geoHash", address(0))); bytes memory data = abi.encode(subgraphDeployment, tokens, _allocationID, abi.encodePacked(r, s, v)); subgraphService.startService(indexer, data); vm.stopPrank(); } - function createIndexingDispute(address _allocationID, uint256 tokens) private returns (bytes32 disputeID) { + function createIndexingDispute(address _allocationID, bytes32 _poi, uint256 tokens) private returns (bytes32 disputeID) { vm.startPrank(fisherman); graphToken.mint(fisherman, tokens); graphToken.approve(address(disputeManager), tokens); - bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, bytes32("POI1234"), tokens); + bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, _poi, tokens); vm.stopPrank(); return _disputeID; } @@ -181,7 +188,7 @@ contract DisputeManagerTest is Test { function testCreateIndexingDispute() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); } @@ -217,7 +224,7 @@ contract DisputeManagerTest is Test { function test_RevertWhen_DisputeAlreadyCreated() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); // Create another dispute with different fisherman address otherFisherman = address(0x5); @@ -227,7 +234,7 @@ contract DisputeManagerTest is Test { graphToken.approve(address(disputeManager), tokens); bytes memory expectedError = abi.encodeWithSignature("DisputeManagerDisputeAlreadyCreated(bytes32)", disputeID); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI1234"), tokens); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1"), tokens); vm.stopPrank(); } @@ -241,7 +248,7 @@ contract DisputeManagerTest is Test { 100 ether ); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI1234"), 50 ether); + disputeManager.createIndexingDispute(allocationID, bytes32("POI3"), 50 ether); vm.stopPrank(); } @@ -253,7 +260,7 @@ contract DisputeManagerTest is Test { graphToken.approve(address(disputeManager), tokens); bytes memory expectedError = abi.encodeWithSignature("DisputeManagerIndexerNotFound(address)", allocationID); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI1234"), tokens); + disputeManager.createIndexingDispute(allocationID, bytes32("POI4"), tokens); vm.stopPrank(); } @@ -316,7 +323,7 @@ contract DisputeManagerTest is Test { function testAcceptIndexingDispute() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); vm.prank(arbitrator); disputeManager.acceptDispute(disputeID, 5000 ether); @@ -371,7 +378,7 @@ contract DisputeManagerTest is Test { function test_RevertIf_CallerIsNotArbitrator_AcceptDispute() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); // attempt to accept dispute as fisherman vm.prank(fisherman); @@ -381,11 +388,11 @@ contract DisputeManagerTest is Test { function test_RevertIf_SlashingOverMaxSlashPercentage() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI101"), 200 ether); // max slashing percentage is 50% vm.prank(arbitrator); - bytes memory expectedError = abi.encodeWithSignature("DisputeManagerInvalidSlashAmount(uint256)", 6000 ether); + bytes memory expectedError = abi.encodeWithSignature("DisputeManagerInvalidTokensSlash(uint256)", 6000 ether); vm.expectRevert(expectedError); disputeManager.acceptDispute(disputeID, 6000 ether); } @@ -394,7 +401,7 @@ contract DisputeManagerTest is Test { function testCancelDispute() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); // skip to end of dispute period skip(disputePeriod + 1); @@ -442,7 +449,7 @@ contract DisputeManagerTest is Test { function test_RevertIf_CallerIsNotFisherman_CancelDispute() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); vm.prank(arbitrator); vm.expectRevert(bytes4(keccak256("DisputeManagerNotFisherman()"))); @@ -453,7 +460,7 @@ contract DisputeManagerTest is Test { function testDrawDispute() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI32"), 200 ether); vm.prank(arbitrator); disputeManager.drawDispute(disputeID); @@ -495,7 +502,7 @@ contract DisputeManagerTest is Test { function test_RevertIf_CallerIsNotArbitrator_DrawDispute() public { createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, 200 ether); + bytes32 disputeID = createIndexingDispute(allocationID,bytes32("POI1"), 200 ether); // attempt to draw dispute as fisherman vm.prank(fisherman); diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index d7b205c5c..d5f1d48d0 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -83,7 +83,7 @@ contract MockHorizonStaking { // provisioned tokens that are not being used // `Provision.tokens - Provision.tokensThawing` - function getTokensAvailable(address serviceProvider, address verifier) external view returns (uint256 tokens) { + function getTokensAvailable(address serviceProvider, address verifier, uint32 delegationRatio) external view returns (uint256 tokens) { return _provisions[verifier][serviceProvider].tokens; } @@ -97,6 +97,14 @@ contract MockHorizonStaking { return true; } + function getDelegationPool(address serviceProvider, address verifier) external view returns (IHorizonStakingTypes.DelegationPool memory) { + return IHorizonStakingTypes.DelegationPool({ + tokens: 0, + shares: 0, + tokensThawing: 0, + sharesThawing: 0 + }); + } function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256 delegationCut) {} function addToDelegationPool(address serviceProvider, uint256 tokens) external {} function stakeToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external {} From df297f77661f247308eb6d240e556b67fc5cfbfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 11 Jun 2024 15:51:43 +0200 Subject: [PATCH 123/277] test: add data service framework tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../utilities/ProvisionManager.sol | 14 +- .../test/data-service/DataService.t.sol | 400 +++++++++++++++++- .../test/data-service/DataService.tree | 72 +++- .../test/data-service/DataServiceBase.sol | 18 - .../data-service/DataServiceUpgradeable.t.sol | 5 +- .../data-service/DataServiceUpgradeable.tree | 3 + .../implementations/DataServiceBase.sol | 59 +++ .../DataServiceBaseUpgradeable.sol | 4 +- .../implementations/DataServiceOverride.sol | 25 ++ .../libraries/ProvisionTracker.t.sol | 19 +- .../HorizonStakingShared.t.sol | 44 +- 11 files changed, 589 insertions(+), 74 deletions(-) delete mode 100644 packages/horizon/test/data-service/DataServiceBase.sol create mode 100644 packages/horizon/test/data-service/DataServiceUpgradeable.tree create mode 100644 packages/horizon/test/data-service/implementations/DataServiceBase.sol rename packages/horizon/test/data-service/{ => implementations}/DataServiceBaseUpgradeable.sol (83%) create mode 100644 packages/horizon/test/data-service/implementations/DataServiceOverride.sol diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index a500febf9..de3580aea 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -58,6 +58,13 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa */ error ProvisionManagerInvalidValue(bytes message, uint256 value, uint256 min, uint256 max); + /** + * @notice Thrown when attempting to set a range where min is greater than max. + * @param min The minimum value. + * @param max The maximum value. + */ + error ProvisionManagerInvalidRange(uint256 min, uint256 max); + /** * @notice Thrown when the caller is not authorized to manage the provision of a service provider. * @param caller The address of the caller. @@ -156,7 +163,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * * @param _serviceProvider The address of the service provider. */ - function _acceptProvisionParameters(address _serviceProvider) internal virtual { + function _acceptProvisionParameters(address _serviceProvider) internal { _checkProvisionParameters(_serviceProvider, true); _graphStaking().acceptProvisionParameters(_serviceProvider); } @@ -177,6 +184,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * @param _max The maximum allowed value for the provision tokens. */ function _setProvisionTokensRange(uint256 _min, uint256 _max) internal { + require(_min <= _max, ProvisionManagerInvalidRange(_min, _max)); minimumProvisionTokens = _min; maximumProvisionTokens = _max; emit ProvisionTokensRangeSet(_min, _max); @@ -188,6 +196,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * @param _max The maximum allowed value for the max verifier cut. */ function _setVerifierCutRange(uint32 _min, uint32 _max) internal { + require(_min <= _max, ProvisionManagerInvalidRange(_min, _max)); minimumVerifierCut = _min; maximumVerifierCut = _max; emit VerifierCutRangeSet(_min, _max); @@ -199,6 +208,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * @param _max The maximum allowed value for the thawing period. */ function _setThawingPeriodRange(uint64 _min, uint64 _max) internal { + require(_min <= _max, ProvisionManagerInvalidRange(_min, _max)); minimumThawingPeriod = _min; maximumThawingPeriod = _max; emit ThawingPeriodRangeSet(_min, _max); @@ -261,7 +271,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * @notice Gets the delegation ratio. * @return The delegation ratio */ - function _getDelegationRatio() internal view virtual returns (uint32) { + function _getDelegationRatio() internal view returns (uint32) { return delegationRatio; } diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol index 66d12d80b..95e027dd3 100644 --- a/packages/horizon/test/data-service/DataService.t.sol +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -1,30 +1,394 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import { GraphBaseTest } from "../GraphBase.t.sol"; -import { DataServiceBase } from "./DataServiceBase.sol"; +import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; +import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; +import { DataServiceBase } from "./implementations/DataServiceBase.sol"; +import { DataServiceOverride } from "./implementations/DataServiceOverride.sol"; +import { ProvisionManager } from "./../../contracts/data-service/utilities/ProvisionManager.sol"; +import { PPMMath } from "./../../contracts/libraries/PPMMath.sol"; -contract DataServiceTest is GraphBaseTest { - function test_WhenTheContractIsDeployedWithAValidController() external { - DataServiceBase dataService = _deployDataService(); +contract DataServiceTest is HorizonStakingSharedTest { + DataServiceBase dataService; + DataServiceOverride dataServiceOverride; - uint32 delegationRatio = dataService.getDelegationRatio(); - assertEq(delegationRatio, type(uint32).min); + function setUp() public override { + super.setUp(); - (uint256 minTokens, uint256 maxTokens) = dataService.getProvisionTokensRange(); - assertEq(minTokens, type(uint256).min); - assertEq(maxTokens, type(uint256).max); + dataService = new DataServiceBase(address(controller)); + dataServiceOverride = new DataServiceOverride(address(controller)); + } + + function test_Constructor_WhenTheContractIsDeployedWithAValidController() external view { + _assert_delegationRatio(type(uint32).min); + _assert_provisionTokens_range(type(uint256).min, type(uint256).max); + _assert_verifierCut_range(type(uint32).min, type(uint32).max); + _assert_thawingPeriod_range(type(uint64).min, type(uint64).max); + } + + // -- Delegation ratio -- + + function test_DelegationRatio_WhenSettingTheDelegationRatio(uint32 delegationRatio) external { + _assert_set_delegationRatio(delegationRatio); + } + + function test_DelegationRatio_WhenGettingTheDelegationRatio(uint32 ratio) external { + dataService.setDelegationRatio(ratio); + _assert_delegationRatio(ratio); + } + + // -- Provision tokens -- + + function test_ProvisionTokens_WhenSettingAValidRange(uint256 min, uint256 max) external { + vm.assume(min <= max); + _assert_set_provisionTokens_range(min, max); + } + + function test_ProvisionTokens_RevertWhen_SettingAnInvalidRange(uint256 min, uint256 max) external { + vm.assume(min > max); + + vm.expectRevert(abi.encodeWithSelector(ProvisionManager.ProvisionManagerInvalidRange.selector, min, max)); + dataService.setProvisionTokensRange(min, max); + } + + function test_ProvisionTokens_WhenGettingTheRange() external { + dataService.setProvisionTokensRange(dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); + _assert_provisionTokens_range(dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); + } + + function test_ProvisionTokens_WhenGettingTheRangeWithAnOverridenGetter() external { + // Overriden getter returns the const values regardless of the set range + dataServiceOverride.setProvisionTokensRange(0, 1); + (uint256 min, uint256 max) = dataServiceOverride.getProvisionTokensRange(); + + assertEq(min, dataServiceOverride.PROVISION_TOKENS_MIN()); + assertEq(max, dataServiceOverride.PROVISION_TOKENS_MAX()); + } + + function test_ProvisionTokens_WhenCheckingAValidProvision(uint256 tokens) external useIndexer { + dataService.setProvisionTokensRange(dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); + tokens = bound(tokens, dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); + + _createProvision(address(dataService), tokens, 0, 0); + dataService.checkProvisionTokens(users.indexer); + } + + function test_ProvisionTokens_WhenCheckingWithAnOverridenChecker(uint256 tokens) external useIndexer { + vm.assume(tokens != 0); + dataServiceOverride.setProvisionTokensRange( + dataService.PROVISION_TOKENS_MIN(), + dataService.PROVISION_TOKENS_MAX() + ); + + // this checker accepts provisions with any amount of tokens + _createProvision(address(dataServiceOverride), tokens, 0, 0); + dataServiceOverride.checkProvisionTokens(users.indexer); + } + + function test_ProvisionTokens_RevertWhen_CheckingAnInvalidProvision(uint256 tokens) external useIndexer { + dataService.setProvisionTokensRange(dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); + tokens = bound(tokens, 1, dataService.PROVISION_TOKENS_MIN() - 1); + + _createProvision(address(dataService), tokens, 0, 0); + vm.expectRevert( + abi.encodeWithSelector( + ProvisionManager.ProvisionManagerInvalidValue.selector, + "tokens", + tokens, + dataService.PROVISION_TOKENS_MIN(), + dataService.PROVISION_TOKENS_MAX() + ) + ); + dataService.checkProvisionTokens(users.indexer); + } + + // -- Verifier cut -- + + function test_VerifierCut_WhenSettingAValidRange(uint32 min, uint32 max) external { + vm.assume(min <= max); + _assert_set_verifierCut_range(min, max); + } + + function test_VerifierCut_RevertWhen_SettingAnInvalidRange(uint32 min, uint32 max) external { + vm.assume(min > max); + + vm.expectRevert(abi.encodeWithSelector(ProvisionManager.ProvisionManagerInvalidRange.selector, min, max)); + dataService.setVerifierCutRange(min, max); + } + + function test_VerifierCut_WhenGettingTheRange() external { + dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + _assert_verifierCut_range(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + } + + function test_VerifierCut_WhenGettingTheRangeWithAnOverridenGetter() external { + // Overriden getter returns the const values regardless of the set range + dataServiceOverride.setVerifierCutRange(0, 1); + (uint32 min, uint32 max) = dataServiceOverride.getVerifierCutRange(); + assertEq(min, dataServiceOverride.VERIFIER_CUT_MIN()); + assertEq(max, dataServiceOverride.VERIFIER_CUT_MAX()); + } + + function test_VerifierCut_WhenCheckingAValidProvision(uint32 verifierCut) external useIndexer { + dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + verifierCut = uint32(bound(verifierCut, dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX())); + + _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); + dataService.checkProvisionParameters(users.indexer, false); + } + + function test_VerifierCut_WhenCheckingWithAnOverridenChecker(uint32 verifierCut) external useIndexer { + verifierCut = uint32(bound(verifierCut, 0, uint32(PPMMath.MAX_PPM))); + dataServiceOverride.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + + // this checker accepts provisions with any verifier cut range + _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); + dataServiceOverride.checkProvisionParameters(users.indexer, false); + } + + function test_VerifierCut_RevertWhen_CheckingAnInvalidProvision(uint32 verifierCut) external useIndexer { + dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + verifierCut = uint32(bound(verifierCut, 0, dataService.VERIFIER_CUT_MIN() - 1)); + + _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); + vm.expectRevert( + abi.encodeWithSelector( + ProvisionManager.ProvisionManagerInvalidValue.selector, + "maxVerifierCut", + verifierCut, + dataService.VERIFIER_CUT_MIN(), + dataService.VERIFIER_CUT_MAX() + ) + ); + dataService.checkProvisionParameters(users.indexer, false); + } + + // -- Thawing period -- - (uint32 minVerifierCut, uint32 maxVerifierCut) = dataService.getVerifierCutRange(); - assertEq(minVerifierCut, type(uint32).min); - assertEq(maxVerifierCut, type(uint32).max); + function test_ThawingPeriod_WhenSettingAValidRange(uint64 min, uint64 max) external { + vm.assume(min <= max); + _assert_set_thawingPeriod_range(min, max); + } + + function test_ThawingPeriod_RevertWhen_SettingAnInvalidRange(uint64 min, uint64 max) external { + vm.assume(min > max); + + vm.expectRevert(abi.encodeWithSelector(ProvisionManager.ProvisionManagerInvalidRange.selector, min, max)); + dataService.setThawingPeriodRange(min, max); + } + + function test_ThawingPeriod_WhenGettingTheRange() external { + dataService.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + _assert_thawingPeriod_range(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + } + + function test_ThawingPeriod_WhenGettingTheRangeWithAnOverridenGetter() external { + // Overriden getter returns the const values regardless of the set range + dataServiceOverride.setThawingPeriodRange(0, 1); + (uint64 min, uint64 max) = dataServiceOverride.getThawingPeriodRange(); + assertEq(min, dataServiceOverride.THAWING_PERIOD_MIN()); + assertEq(max, dataServiceOverride.THAWING_PERIOD_MAX()); + } + + function test_ThawingPeriod_WhenCheckingAValidProvision(uint64 thawingPeriod) external useIndexer { + dataService.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + thawingPeriod = uint32( + bound(thawingPeriod, dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()) + ); + + _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); + dataService.checkProvisionParameters(users.indexer, false); + } + + function test_ThawingPeriod_WhenCheckingWithAnOverridenChecker(uint64 thawingPeriod) external useIndexer { + thawingPeriod = uint32(bound(thawingPeriod, 0, staking.getMaxThawingPeriod())); + dataServiceOverride.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + + // this checker accepts provisions with any verifier cut range + _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); + dataServiceOverride.checkProvisionParameters(users.indexer, false); + } + + function test_ThawingPeriod_RevertWhen_CheckingAnInvalidProvision(uint64 thawingPeriod) external useIndexer { + dataService.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + thawingPeriod = uint32(bound(thawingPeriod, 0, dataService.THAWING_PERIOD_MIN() - 1)); + + _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); + vm.expectRevert( + abi.encodeWithSelector( + ProvisionManager.ProvisionManagerInvalidValue.selector, + "thawingPeriod", + thawingPeriod, + dataService.THAWING_PERIOD_MIN(), + dataService.THAWING_PERIOD_MAX() + ) + ); + dataService.checkProvisionParameters(users.indexer, false); + } + + modifier givenProvisionParametersChanged() { + _; + } + + function test_ProvisionParameters_WhenTheNewParametersAreValid( + uint32 maxVerifierCut, + uint64 thawingPeriod + ) external givenProvisionParametersChanged useIndexer { + // bound to valid values + maxVerifierCut = uint32(bound(maxVerifierCut, dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX())); + thawingPeriod = uint64(bound(thawingPeriod, dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX())); + + // set provision parameter ranges + dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + dataService.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + + // stage provision parameter changes + _createProvision( + address(dataService), + dataService.PROVISION_TOKENS_MIN(), + dataService.VERIFIER_CUT_MIN(), + dataService.THAWING_PERIOD_MIN() + ); + staking.setProvisionParameters( + users.indexer, + address(dataService), + maxVerifierCut, + thawingPeriod + ); + + // accept provision parameters + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersSet( + users.indexer, + address(dataService), + maxVerifierCut, + thawingPeriod + ); + dataService.acceptProvisionParameters(users.indexer); + } + + function test_ProvisionParameters_RevertWhen_TheNewThawingPeriodIsInvalid( + uint64 thawingPeriod + ) external givenProvisionParametersChanged useIndexer { + // bound to invalid values + thawingPeriod = uint64(bound(thawingPeriod, 0, dataService.THAWING_PERIOD_MIN() - 1)); + + // set provision parameter ranges + dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + dataService.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + + // stage provision parameter changes + _createProvision( + address(dataService), + dataService.PROVISION_TOKENS_MIN(), + dataService.VERIFIER_CUT_MIN(), + dataService.THAWING_PERIOD_MIN() + ); + staking.setProvisionParameters( + users.indexer, + address(dataService), + dataService.VERIFIER_CUT_MIN(), + thawingPeriod + ); + + // accept provision parameters + vm.expectRevert( + abi.encodeWithSelector( + ProvisionManager.ProvisionManagerInvalidValue.selector, + "thawingPeriod", + thawingPeriod, + dataService.THAWING_PERIOD_MIN(), + dataService.THAWING_PERIOD_MAX() + ) + ); + dataService.acceptProvisionParameters(users.indexer); + } + + function test_ProvisionParameters_RevertWhen_TheNewVerifierCutIsInvalid( + uint32 maxVerifierCut + ) external givenProvisionParametersChanged useIndexer { + // bound to valid values + maxVerifierCut = uint32(bound(maxVerifierCut, dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX())); + + // set provision parameter ranges + dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); + dataService.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); + + // stage provision parameter changes + _createProvision( + address(dataService), + dataService.PROVISION_TOKENS_MIN(), + dataService.VERIFIER_CUT_MIN(), + dataService.THAWING_PERIOD_MIN() + ); + staking.setProvisionParameters( + users.indexer, + address(dataService), + maxVerifierCut, + dataService.THAWING_PERIOD_MIN() + ); + + // accept provision parameters + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersSet( + users.indexer, + address(dataService), + maxVerifierCut, + dataService.THAWING_PERIOD_MIN() + ); + dataService.acceptProvisionParameters(users.indexer); + } + + // -- Assert functions -- + + function _assert_set_delegationRatio(uint32 ratio) internal { + vm.expectEmit(); + emit ProvisionManager.DelegationRatioSet(ratio); + dataService.setDelegationRatio(ratio); + _assert_delegationRatio(ratio); + } + + function _assert_delegationRatio(uint32 ratio) internal view { + uint32 _delegationRatio = dataService.getDelegationRatio(); + assertEq(_delegationRatio, ratio); + } + + function _assert_set_provisionTokens_range(uint256 min, uint256 max) internal { + vm.expectEmit(); + emit ProvisionManager.ProvisionTokensRangeSet(min, max); + dataService.setProvisionTokensRange(min, max); + _assert_provisionTokens_range(min, max); + } + + function _assert_provisionTokens_range(uint256 min, uint256 max) internal view { + (uint256 _min, uint256 _max) = dataService.getProvisionTokensRange(); + assertEq(_min, min); + assertEq(_max, max); + } + + function _assert_set_verifierCut_range(uint32 min, uint32 max) internal { + vm.expectEmit(); + emit ProvisionManager.VerifierCutRangeSet(min, max); + dataService.setVerifierCutRange(min, max); + _assert_verifierCut_range(min, max); + } + + function _assert_verifierCut_range(uint32 min, uint32 max) internal view { + (uint32 _min, uint32 _max) = dataService.getVerifierCutRange(); + assertEq(_min, min); + assertEq(_max, max); + } - (uint64 minThawingPeriod, uint64 maxThawingPeriod) = dataService.getThawingPeriodRange(); - assertEq(minThawingPeriod, type(uint64).min); - assertEq(maxThawingPeriod, type(uint64).max); + function _assert_set_thawingPeriod_range(uint64 min, uint64 max) internal { + vm.expectEmit(); + emit ProvisionManager.ThawingPeriodRangeSet(min, max); + dataService.setThawingPeriodRange(min, max); + _assert_thawingPeriod_range(min, max); } - function _deployDataService() internal returns (DataServiceBase) { - return new DataServiceBase(address(controller)); + function _assert_thawingPeriod_range(uint64 min, uint64 max) internal view { + (uint64 _min, uint64 _max) = dataService.getThawingPeriodRange(); + assertEq(_min, min); + assertEq(_max, max); } } diff --git a/packages/horizon/test/data-service/DataService.tree b/packages/horizon/test/data-service/DataService.tree index 2a71bce48..cd016608e 100644 --- a/packages/horizon/test/data-service/DataService.tree +++ b/packages/horizon/test/data-service/DataService.tree @@ -1,3 +1,71 @@ -DataService +DataServiceTest::constructor_ └── when the contract is deployed with a valid controller - └── it should set all it's ranges to max \ No newline at end of file + └── it should set all it's ranges to max + +DataServiceTest::delegationRatio_ +├── when setting the delegation ratio +│ ├── it should emit an event +│ └── it should set the range +└── when getting the delegation ratio + └── it should return the correct value + +DataServiceTest::provisionTokens_ +├── when setting a valid range +│ ├── it should emit an event +│ └── it should set the range +├── when setting an invalid range +│ └── it should revert +├── when getting the range +│ └── it should return the correct value +├── when getting the range with an overriden getter +│ └── it should return the correct value +├── when checking a valid provision +│ └── it should not revert +├── when checking with an overriden checker +│ └── it should not revert +└── when checking an invalid provision + └── it should revert + +DataServiceTest::verifierCut_ +├── when setting a valid range +│ ├── it should emit an event +│ └── it should set the range +├── when setting an invalid range +│ └── it should revert +├── when getting the range +│ └── it should return the correct value +├── when getting the range with an overriden getter +│ └── it should return the correct value +├── when checking a valid provision +│ └── it should not revert +├── when checking with an overriden checker +│ └── it should not revert +└── when checking an invalid provision + └── it should revert + +DataServiceTest::thawingPeriod_ +├── when setting a valid range +│ ├── it should emit an event +│ └── it should set the range +├── when setting an invalid range +│ └── it should revert +├── when getting the range +│ └── it should return the correct value +├── when getting the range with an overriden getter +│ └── it should return the correct value +├── when checking a valid provision +│ └── it should not revert +├── when checking with an overriden checker +│ └── it should not revert +└── when checking an invalid provision + └── it should revert + +DataServiceTest::provisionParameters_ +└── given provision parameters changed + ├── when the new parameters are valid + │ ├── it should emit an event + │ └── it should set the new parameters + ├── when the new thawing period is invalid + │ └── it should revert + └── when the new verifier cut is invalid + └── it should revert \ No newline at end of file diff --git a/packages/horizon/test/data-service/DataServiceBase.sol b/packages/horizon/test/data-service/DataServiceBase.sol deleted file mode 100644 index 5103d51c5..000000000 --- a/packages/horizon/test/data-service/DataServiceBase.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; - -import { DataService } from "../../contracts/data-service/DataService.sol"; -import { IGraphPayments } from "./../../contracts/interfaces/IGraphPayments.sol"; - -contract DataServiceBase is DataService { - constructor(address controller) DataService(controller) initializer { - __DataService_init(); - } - - function register(address serviceProvider, bytes calldata data) external {} - function acceptProvision(address serviceProvider, bytes calldata data) external {} - function startService(address serviceProvider, bytes calldata data) external {} - function stopService(address serviceProvider, bytes calldata data) external {} - function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} - function slash(address serviceProvider, bytes calldata data) external {} -} diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol index 49ddec3d7..dff804a2b 100644 --- a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol +++ b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol @@ -2,9 +2,8 @@ pragma solidity 0.8.26; import { GraphBaseTest } from "../GraphBase.t.sol"; -import { DataServiceBaseUpgradeable } from "./DataServiceBaseUpgradeable.sol"; +import { DataServiceBaseUpgradeable } from "./implementations/DataServiceBaseUpgradeable.sol"; import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; -import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract DataServiceUpgradeableTest is GraphBaseTest { function test_WhenTheContractIsDeployedWithAValidController() external { @@ -30,7 +29,7 @@ contract DataServiceUpgradeableTest is GraphBaseTest { // Deploy implementation address implementation = address(new DataServiceBaseUpgradeable(address(controller))); - // Deploy proxy (calls initialize) + // Deploy proxy address proxy = UnsafeUpgrades.deployTransparentProxy( implementation, users.governor, diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.tree b/packages/horizon/test/data-service/DataServiceUpgradeable.tree new file mode 100644 index 000000000..dbb433635 --- /dev/null +++ b/packages/horizon/test/data-service/DataServiceUpgradeable.tree @@ -0,0 +1,3 @@ +DataServiceUpgradeableTest +└── when the contract is deployed with a valid controller + └── it should set all it's ranges to max \ No newline at end of file diff --git a/packages/horizon/test/data-service/implementations/DataServiceBase.sol b/packages/horizon/test/data-service/implementations/DataServiceBase.sol new file mode 100644 index 000000000..1742efc12 --- /dev/null +++ b/packages/horizon/test/data-service/implementations/DataServiceBase.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { DataService } from "../../../contracts/data-service/DataService.sol"; +import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; + +contract DataServiceBase is DataService { + uint32 public constant DELEGATION_RATIO = 100; + uint256 public constant PROVISION_TOKENS_MIN = 50; + uint256 public constant PROVISION_TOKENS_MAX = 5000; + uint32 public constant VERIFIER_CUT_MIN = 5; + uint32 public constant VERIFIER_CUT_MAX = 100000; + uint64 public constant THAWING_PERIOD_MIN = 15; + uint64 public constant THAWING_PERIOD_MAX = 76; + + constructor(address controller) DataService(controller) initializer { + __DataService_init(); + } + + function register(address serviceProvider, bytes calldata data) external {} + + function acceptProvision(address serviceProvider, bytes calldata data) external {} + + function startService(address serviceProvider, bytes calldata data) external {} + + function stopService(address serviceProvider, bytes calldata data) external {} + + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + + function slash(address serviceProvider, bytes calldata data) external {} + + function setDelegationRatio(uint32 ratio) external { + _setDelegationRatio(ratio); + } + + function setProvisionTokensRange(uint256 min, uint256 max) external { + _setProvisionTokensRange(min, max); + } + + function setVerifierCutRange(uint32 min, uint32 max) external { + _setVerifierCutRange(min, max); + } + + function setThawingPeriodRange(uint64 min, uint64 max) external { + _setThawingPeriodRange(min, max); + } + + function checkProvisionTokens(address serviceProvider) external view { + _checkProvisionTokens(serviceProvider); + } + + function checkProvisionParameters(address serviceProvider, bool pending) external view { + _checkProvisionParameters(serviceProvider, pending); + } + + function acceptProvisionParameters(address serviceProvider) external { + _acceptProvisionParameters(serviceProvider); + } +} diff --git a/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol similarity index 83% rename from packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol rename to packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol index 00f2b485b..9913c1b76 100644 --- a/packages/horizon/test/data-service/DataServiceBaseUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; -import { DataService } from "../../contracts/data-service/DataService.sol"; -import { IGraphPayments } from "./../../contracts/interfaces/IGraphPayments.sol"; +import { DataService } from "../../../contracts/data-service/DataService.sol"; +import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; contract DataServiceBaseUpgradeable is DataService { constructor(address controller) DataService(controller) { diff --git a/packages/horizon/test/data-service/implementations/DataServiceOverride.sol b/packages/horizon/test/data-service/implementations/DataServiceOverride.sol new file mode 100644 index 000000000..838be68a5 --- /dev/null +++ b/packages/horizon/test/data-service/implementations/DataServiceOverride.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { DataServiceBase } from "./DataServiceBase.sol"; + +contract DataServiceOverride is DataServiceBase { + constructor(address controller) DataServiceBase(controller) initializer { + __DataService_init(); + } + + function _getProvisionTokensRange() internal pure override returns (uint256, uint256) { + return (PROVISION_TOKENS_MIN, PROVISION_TOKENS_MAX); + } + + function _getVerifierCutRange() internal pure override returns (uint32, uint32) { + return (VERIFIER_CUT_MIN, VERIFIER_CUT_MAX); + } + + function _getThawingPeriodRange() internal pure override returns (uint64, uint64) { + return (THAWING_PERIOD_MIN, THAWING_PERIOD_MAX); + } + + function _checkProvisionTokens(address _serviceProvider) internal pure override {} + function _checkProvisionParameters(address _serviceProvider, bool pending) internal pure override {} +} diff --git a/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol b/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol index 6155bf4c7..a7ec2f614 100644 --- a/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol +++ b/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol @@ -28,21 +28,10 @@ library ProvisionTrackerWrapper { contract ProvisionTrackerTest is HorizonStakingSharedTest, ProvisionTrackerImplementation { using ProvisionTrackerWrapper for mapping(address => uint256); - modifier useProvision( - uint256 tokens, - uint32, - uint64 - ) override { - vm.assume(tokens > 0); - vm.assume(tokens <= MAX_STAKING_TOKENS); - _createProvision(address(this), tokens, 0, 0); - _; - } - function test_Lock_GivenTheProvisionHasSufficientAvailableTokens( uint256 tokens, uint256 steps - ) external useIndexer useProvision(tokens, 0, 0) { + ) external useIndexer useProvisionDataService(address(this), tokens, 0, 0) { vm.assume(tokens > 0); vm.assume(steps > 0); vm.assume(steps < 100); @@ -63,7 +52,7 @@ contract ProvisionTrackerTest is HorizonStakingSharedTest, ProvisionTrackerImple function test_Lock_RevertGiven_TheProvisionHasInsufficientAvailableTokens( uint256 tokens - ) external useIndexer useProvision(tokens, 0, 0) { + ) external useIndexer useProvisionDataService(address(this), tokens, 0, 0) { uint256 tokensToLock = tokens + 1; vm.expectRevert( abi.encodeWithSelector(ProvisionTracker.ProvisionTrackerInsufficientTokens.selector, tokens, tokensToLock) @@ -74,7 +63,7 @@ contract ProvisionTrackerTest is HorizonStakingSharedTest, ProvisionTrackerImple function test_Release_GivenTheProvisionHasSufficientLockedTokens( uint256 tokens, uint256 steps - ) external useIndexer useProvision(tokens, 0, 0) { + ) external useIndexer useProvisionDataService(address(this), tokens, 0, 0) { vm.assume(tokens > 0); vm.assume(steps > 0); vm.assume(steps < 100); @@ -97,7 +86,7 @@ contract ProvisionTrackerTest is HorizonStakingSharedTest, ProvisionTrackerImple assertEq(provisionTracker[users.indexer], delta); } - function test_Release_RevertGiven_TheProvisionHasInsufficientLockedTokens(uint256 tokens) external useIndexer useProvision(tokens, 0, 0) { + function test_Release_RevertGiven_TheProvisionHasInsufficientLockedTokens(uint256 tokens) external useIndexer useProvisionDataService(address(this), tokens, 0, 0) { // setup provisionTracker.lock(staking, users.indexer, tokens, uint32(0)); diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 8ab125dcb..9a30f53cc 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -7,7 +7,6 @@ import { GraphBaseTest } from "../../GraphBase.t.sol"; import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol"; abstract contract HorizonStakingSharedTest is GraphBaseTest { - /* * MODIFIERS */ @@ -24,12 +23,22 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { _; } - modifier useProvision(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) virtual { - vm.assume(tokens <= MAX_STAKING_TOKENS); - vm.assume(tokens > 0); - vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); - vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); - _createProvision(subgraphDataServiceAddress, tokens, maxVerifierCut, thawingPeriod); + modifier useProvision( + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) virtual { + _useProvision(subgraphDataServiceAddress, tokens, maxVerifierCut, thawingPeriod); + _; + } + + modifier useProvisionDataService( + address dataService, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) { + _useProvision(dataService, tokens, maxVerifierCut, thawingPeriod); _; } @@ -42,6 +51,19 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { * HELPERS */ + function _useProvision( + address dataService, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) internal { + vm.assume(tokens <= MAX_STAKING_TOKENS); + vm.assume(tokens > 0); + vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); + vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); + _createProvision(dataService, tokens, maxVerifierCut, thawingPeriod); + } + function _createProvision( address dataServiceAddress, uint256 tokens, @@ -50,13 +72,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { ) internal { token.approve(address(staking), tokens); staking.stakeTo(users.indexer, tokens); - staking.provision( - users.indexer, - dataServiceAddress, - tokens, - maxVerifierCut, - thawingPeriod - ); + staking.provision(users.indexer, dataServiceAddress, tokens, maxVerifierCut, thawingPeriod); } function _setDelegationFeeCut(IGraphPayments.PaymentTypes paymentType, uint256 cut) internal { From e5c3ec1235c3d66cd534328220f8bee49215c874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 11 Jun 2024 16:03:46 +0200 Subject: [PATCH 124/277] chore: linting stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/.solhintignore | 1 + .../internal/IHorizonStakingExtension.sol | 1 + .../staking/HorizonStakingExtension.sol | 22 ++++++++++--------- 3 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 packages/horizon/.solhintignore diff --git a/packages/horizon/.solhintignore b/packages/horizon/.solhintignore new file mode 100644 index 000000000..a0367e1af --- /dev/null +++ b/packages/horizon/.solhintignore @@ -0,0 +1 @@ +contracts/mocks/* \ No newline at end of file diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index d0331580e..80fc52ea0 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -164,5 +164,6 @@ interface IHorizonStakingExtension is IRewardsIssuer { * @notice Retrun the time in blocks to unstake * @return Thawing period in blocks */ + // solhint-disable-next-line func-name-mixedcase function __DEPRECATED_getThawingPeriod() external view returns (uint64); } diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 7931c2988..9667d35bb 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -294,6 +294,16 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon return _serviceProviders[indexer].tokensStaked > 0; } + /** + * @notice Retrun the time in blocks to unstake + * Deprecated, now enforced by each data service (verifier) + * @return Thawing period in blocks + */ + // solhint-disable-next-line func-name-mixedcase + function __DEPRECATED_getThawingPeriod() external view returns (uint64) { + return __DEPRECATED_thawingPeriod; + } + /** * @notice (Legacy) Return true if operator is allowed for the service provider on the subgraph data service. * @dev TODO: Delete after the transition period @@ -305,15 +315,6 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon return _legacyOperatorAuth[serviceProvider][operator]; } - /** - * @notice Retrun the time in blocks to unstake - * Deprecated, now enforced by each data service (verifier) - * @return Thawing period in blocks - */ - function __DEPRECATED_getThawingPeriod() external view returns (uint64) { - return __DEPRECATED_thawingPeriod; - } - /** * @dev Receive an Indexer's stake from L1. * The specified amount is added to the indexer's stake; the indexer's @@ -450,7 +451,8 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon // Anyone is allowed to close ONLY under two concurrent conditions // - After maxAllocationEpochs passed // - When the allocation is for non-zero amount of tokens - bool isIndexerOrOperator = msg.sender == alloc.indexer || isOperator(alloc.indexer, SUBGRAPH_DATA_SERVICE_ADDRESS); + bool isIndexerOrOperator = msg.sender == alloc.indexer || + isOperator(alloc.indexer, SUBGRAPH_DATA_SERVICE_ADDRESS); if (epochs <= __DEPRECATED_maxAllocationEpochs || alloc.tokens == 0) { require(isIndexerOrOperator, "!auth"); } From bc4aba10aaa2c3a610645b86d1c6ed44d009ee1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 11 Jun 2024 16:05:49 +0200 Subject: [PATCH 125/277] chore: more linting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/contracts/mocks/CurationMock.sol | 1 - packages/horizon/contracts/mocks/EpochManagerMock.sol | 5 ++--- packages/horizon/contracts/mocks/RewardsManagerMock.sol | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/horizon/contracts/mocks/CurationMock.sol b/packages/horizon/contracts/mocks/CurationMock.sol index b480673fd..402a07e4c 100644 --- a/packages/horizon/contracts/mocks/CurationMock.sol +++ b/packages/horizon/contracts/mocks/CurationMock.sol @@ -5,7 +5,6 @@ pragma solidity 0.8.26; import { MockGRTToken } from "./MockGRTToken.sol"; contract CurationMock { - mapping(bytes32 => uint256) public curation; function signal(bytes32 _subgraphDeploymentID, uint256 _tokens) public { diff --git a/packages/horizon/contracts/mocks/EpochManagerMock.sol b/packages/horizon/contracts/mocks/EpochManagerMock.sol index 82b51d855..b76714e50 100644 --- a/packages/horizon/contracts/mocks/EpochManagerMock.sol +++ b/packages/horizon/contracts/mocks/EpochManagerMock.sol @@ -5,14 +5,13 @@ pragma solidity 0.8.26; import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; contract EpochManagerMock is IEpochManager { - // -- Variables -- - + uint256 public epochLength; uint256 public lastRunEpoch; uint256 public lastLengthUpdateEpoch; uint256 public lastLengthUpdateBlock; - + // -- Configuration -- function setEpochLength(uint256 _epochLength) public { diff --git a/packages/horizon/contracts/mocks/RewardsManagerMock.sol b/packages/horizon/contracts/mocks/RewardsManagerMock.sol index 9473e6dbc..2388d99b6 100644 --- a/packages/horizon/contracts/mocks/RewardsManagerMock.sol +++ b/packages/horizon/contracts/mocks/RewardsManagerMock.sol @@ -5,7 +5,6 @@ pragma solidity 0.8.26; import { MockGRTToken } from "./MockGRTToken.sol"; contract RewardsManagerMock { - // -- Variables -- MockGRTToken public token; uint256 private rewards; From 203a3b049fad608b3b7906262b17a032dd336bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 11 Jun 2024 17:19:04 +0200 Subject: [PATCH 126/277] fix: require params change when calling set provision parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../internal/IHorizonStakingMain.sol | 2 +- .../contracts/staking/HorizonStaking.sol | 18 ++- .../test/data-service/DataService.t.sol | 27 +++-- .../horizon/test/staking/HorizonStaking.t.sol | 7 ++ .../test/staking/provision/parameters.t.sol | 104 ++++++++++++++++++ 5 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 packages/horizon/test/staking/provision/parameters.t.sol diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 0118479a1..a6f18c66c 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -612,7 +612,7 @@ interface IHorizonStakingMain { * @dev This two step update process prevents the service provider from changing the parameters * without the verifier's consent. * - * Emits a {ProvisionParametersStaged} event. + * Emits a {ProvisionParametersStaged} event if at least one of the parameters changed. * * @param serviceProvider The service provider address * @param verifier The verifier address diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index d63b655c2..6b02c86c8 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -230,9 +230,13 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint64 thawingPeriod ) external override notPaused onlyAuthorized(serviceProvider, verifier) { Provision storage prov = _provisions[serviceProvider][verifier]; - prov.maxVerifierCutPending = maxVerifierCut; - prov.thawingPeriodPending = thawingPeriod; - emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); + require(prov.createdAt != 0, HorizonStakingInvalidProvision(serviceProvider, verifier)); + + if ((prov.maxVerifierCutPending != maxVerifierCut) || (prov.thawingPeriodPending != thawingPeriod)) { + prov.maxVerifierCutPending = maxVerifierCut; + prov.thawingPeriodPending = thawingPeriod; + emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); + } } /** @@ -241,9 +245,11 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { function acceptProvisionParameters(address serviceProvider) external override notPaused { address verifier = msg.sender; Provision storage prov = _provisions[serviceProvider][verifier]; - prov.maxVerifierCut = prov.maxVerifierCutPending; - prov.thawingPeriod = prov.thawingPeriodPending; - emit ProvisionParametersSet(serviceProvider, verifier, prov.maxVerifierCut, prov.thawingPeriod); + if ((prov.maxVerifierCutPending != prov.maxVerifierCut) || (prov.thawingPeriodPending != prov.thawingPeriod)) { + prov.maxVerifierCut = prov.maxVerifierCutPending; + prov.thawingPeriod = prov.thawingPeriodPending; + emit ProvisionParametersSet(serviceProvider, verifier, prov.maxVerifierCut, prov.thawingPeriod); + } } /* diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol index 95e027dd3..ecba7ae52 100644 --- a/packages/horizon/test/data-service/DataService.t.sol +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -236,7 +236,9 @@ contract DataServiceTest is HorizonStakingSharedTest { ) external givenProvisionParametersChanged useIndexer { // bound to valid values maxVerifierCut = uint32(bound(maxVerifierCut, dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX())); - thawingPeriod = uint64(bound(thawingPeriod, dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX())); + thawingPeriod = uint64( + bound(thawingPeriod, dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()) + ); // set provision parameter ranges dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); @@ -249,12 +251,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataService.VERIFIER_CUT_MIN(), dataService.THAWING_PERIOD_MIN() ); - staking.setProvisionParameters( - users.indexer, - address(dataService), - maxVerifierCut, - thawingPeriod - ); + staking.setProvisionParameters(users.indexer, address(dataService), maxVerifierCut, thawingPeriod); // accept provision parameters vm.expectEmit(); @@ -329,13 +326,15 @@ contract DataServiceTest is HorizonStakingSharedTest { ); // accept provision parameters - vm.expectEmit(); - emit IHorizonStakingMain.ProvisionParametersSet( - users.indexer, - address(dataService), - maxVerifierCut, - dataService.THAWING_PERIOD_MIN() - ); + if (maxVerifierCut != dataService.VERIFIER_CUT_MIN()) { + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersSet( + users.indexer, + address(dataService), + maxVerifierCut, + dataService.THAWING_PERIOD_MIN() + ); + } dataService.acceptProvisionParameters(users.indexer); } diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index bb3703b34..ec3248f39 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -12,6 +12,13 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { * MODIFIERS */ + modifier usePausedStaking() { + vm.startPrank(users.governor); + controller.setPaused(true); + vm.stopPrank(); + _; + } + modifier useOperator() { vm.startPrank(users.indexer); staking.setOperator(users.operator, subgraphDataServiceAddress, true); diff --git a/packages/horizon/test/staking/provision/parameters.t.sol b/packages/horizon/test/staking/provision/parameters.t.sol new file mode 100644 index 000000000..298059a7a --- /dev/null +++ b/packages/horizon/test/staking/provision/parameters.t.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; + +contract HorizonStakingProvisionParametersTest is HorizonStakingTest { + /* + * TESTS + */ + + function test_ProvisionParametersSet( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, 0, 0) { + vm.assume(maxVerifierCut != 0); + vm.assume(thawingPeriod != 0); + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersStaged( + users.indexer, + subgraphDataServiceAddress, + maxVerifierCut, + thawingPeriod + ); + staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + + Provision memory prov = staking.getProvision(users.indexer, subgraphDataServiceAddress); + assertEq(prov.maxVerifierCutPending, maxVerifierCut); + assertEq(prov.thawingPeriodPending, thawingPeriod); + } + + function test_ProvisionParametersSet_RevertWhen_ProvisionNotExists( + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer { + vm.expectRevert( + abi.encodeWithSignature( + "HorizonStakingInvalidProvision(address,address)", + users.indexer, + subgraphDataServiceAddress + ) + ); + staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + } + + function test_ProvisionParametersSet_RevertWhen_CallerNotAuthorized( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + vm.startPrank(msg.sender); // stop impersonating the indexer + vm.expectRevert( + abi.encodeWithSignature( + "HorizonStakingNotAuthorized(address,address,address)", + msg.sender, + users.indexer, + subgraphDataServiceAddress + ) + ); + staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + vm.stopPrank(); + } + + function test_ProvisionParametersSet_RevertWhen_ProtocolPaused( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) usePausedStaking { + vm.expectRevert(abi.encodeWithSignature("ManagedIsPaused()")); + staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + } + + function test_ProvisionParametersAccept( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + Provision memory prov = staking.getProvision(users.indexer, subgraphDataServiceAddress); + + staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + + vm.startPrank(subgraphDataServiceAddress); + + if (maxVerifierCut != prov.maxVerifierCut || thawingPeriod != prov.thawingPeriod) { + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersSet( + users.indexer, + subgraphDataServiceAddress, + maxVerifierCut, + thawingPeriod + ); + } + staking.acceptProvisionParameters(users.indexer); + vm.stopPrank(); + + assertEq(prov.maxVerifierCut, maxVerifierCut); + assertEq(prov.maxVerifierCutPending, maxVerifierCut); + assertEq(prov.thawingPeriod, thawingPeriod); + assertEq(prov.thawingPeriodPending, thawingPeriod); + } +} From da34d9bd7035a89d72878834c2de5de0a0162415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 12 Jun 2024 11:08:28 +0200 Subject: [PATCH 127/277] test: add tests for DataServicePausable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServicePausable.sol | 2 +- packages/horizon/test/GraphBase.t.sol | 3 + .../extensions/DataServicePausable.t.sol | 94 +++++++++++++++++++ .../extensions/DataServicePausable.tree | 23 +++++ .../DataServiceImpPausable.sol | 36 +++++++ 5 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 packages/horizon/test/data-service/extensions/DataServicePausable.t.sol create mode 100644 packages/horizon/test/data-service/extensions/DataServicePausable.tree create mode 100644 packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index 577db9677..404876dc6 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -50,7 +50,7 @@ abstract contract DataServicePausable is Pausable, DataService, IDataServicePaus * @param _pauseGuardian The address of the pause guardian * @param _allowed The allowed status of the pause guardian */ - function _setPauseGuardian(address _pauseGuardian, bool _allowed) internal whenNotPaused { + function _setPauseGuardian(address _pauseGuardian, bool _allowed) internal { pauseGuardians[_pauseGuardian] = _allowed; emit PauseGuardianSet(_pauseGuardian, _allowed); } diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index b978fba2d..fec51c345 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -84,6 +84,9 @@ abstract contract GraphBaseTest is Utils, Constants { vm.label({ account: address(escrow), newLabel: "PaymentsEscrow" }); vm.label({ account: address(staking), newLabel: "HorizonStaking" }); vm.label({ account: address(stakingExtension), newLabel: "HorizonStakingExtension" }); + + // Ensure caller is back to the original msg.sender + vm.stopPrank(); } function deployProtocolContracts() private { diff --git a/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol b/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol new file mode 100644 index 000000000..e65f579f5 --- /dev/null +++ b/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; +import {HorizonStakingSharedTest} from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; +import {DataServiceImpPausable} from "../implementations/DataServiceImpPausable.sol"; +import {IDataServicePausable} from "./../../../contracts/data-service/interfaces/IDataServicePausable.sol"; + +contract DataServicePausableTest is HorizonStakingSharedTest { + DataServiceImpPausable dataService; + + event Paused(address pauser); + event Unpaused(address unpauser); + + function setUp() public override { + super.setUp(); + + dataService = new DataServiceImpPausable(address(controller)); + } + + modifier whenTheCallerIsAPauseGuardian() { + _assert_setPauseGuardian(address(this), true); + _; + } + + function test_Pause_WhenTheProtocolIsNotPaused() external whenTheCallerIsAPauseGuardian { + _assert_pause(); + } + + function test_Pause_RevertWhen_TheProtocolIsPaused() external whenTheCallerIsAPauseGuardian { + _assert_pause(); + + vm.expectRevert(abi.encodeWithSignature("EnforcedPause()")); + dataService.pause(); + assertEq(dataService.paused(), true); + } + + function test_Pause_RevertWhen_TheCallerIsNotAPauseGuardian() external { + vm.expectRevert(abi.encodeWithSignature("DataServicePausableNotPauseGuardian(address)", address(this))); + dataService.pause(); + assertEq(dataService.paused(), false); + } + + function test_Unpause_WhenTheProtocolIsPaused() external whenTheCallerIsAPauseGuardian { + _assert_pause(); + _assert_unpause(); + } + + function test_Unpause_RevertWhen_TheProtocolIsNotPaused() external whenTheCallerIsAPauseGuardian { + vm.expectRevert(abi.encodeWithSignature("ExpectedPause()")); + dataService.unpause(); + assertEq(dataService.paused(), false); + } + + function test_Unpause_RevertWhen_TheCallerIsNotAPauseGuardian() external { + _assert_setPauseGuardian(address(this), true); + _assert_pause(); + _assert_setPauseGuardian(address(this), false); + + vm.expectRevert(abi.encodeWithSignature("DataServicePausableNotPauseGuardian(address)", address(this))); + dataService.unpause(); + assertEq(dataService.paused(), true); + } + + function test_SetPauseGuardian_WhenSettingAPauseGuardian() external { + _assert_setPauseGuardian(address(this), true); + } + + function test_SetPauseGuardian_WhenRemovingAPauseGuardian() external { + _assert_setPauseGuardian(address(this), true); + _assert_setPauseGuardian(address(this), false); + } + + function _assert_pause() private { + vm.expectEmit(); + emit Paused(address(this)); + dataService.pause(); + assertEq(dataService.paused(), true); + } + + function _assert_unpause() private { + vm.expectEmit(); + emit Unpaused(address(this)); + dataService.unpause(); + assertEq(dataService.paused(), false); + } + + function _assert_setPauseGuardian(address pauseGuardian, bool allowed) private { + vm.expectEmit(); + emit IDataServicePausable.PauseGuardianSet(pauseGuardian, allowed); + dataService.setPauseGuardian(pauseGuardian, allowed); + assertEq(dataService.pauseGuardians(pauseGuardian), allowed); + } +} diff --git a/packages/horizon/test/data-service/extensions/DataServicePausable.tree b/packages/horizon/test/data-service/extensions/DataServicePausable.tree new file mode 100644 index 000000000..9a3692026 --- /dev/null +++ b/packages/horizon/test/data-service/extensions/DataServicePausable.tree @@ -0,0 +1,23 @@ +DataServicePausableTest::pause_ +├── when the caller is a pause guardian +│ ├── when the protocol is not paused +│ │ └── it should pause the contract +│ └── when the protocol is paused +│ └── it should revert +└── when the caller is not a pause guardian + └── it should revert + +DataServicePausableTest::unpause_ +├── when the caller is a pause guardian +│ ├── when the protocol is paused +│ │ └── it should unpause the contract +│ └── when the protocol is not paused +│ └── it should revert +└── when the caller is not a pause guardian + └── it should revert + +DataServicePausableTest::setPauseGuardian_ +├── when setting a pause guardian +│ └── it should emit an event +└── when removing a pause guardian + └── it should emit an event \ No newline at end of file diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol new file mode 100644 index 000000000..ff40733b2 --- /dev/null +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { DataService } from "../../../contracts/data-service/DataService.sol"; +import { DataServicePausable } from "../../../contracts/data-service/extensions/DataServicePausable.sol"; +import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; + +contract DataServiceImpPausable is DataServicePausable { + uint32 public constant DELEGATION_RATIO = 100; + uint256 public constant PROVISION_TOKENS_MIN = 50; + uint256 public constant PROVISION_TOKENS_MAX = 5000; + uint32 public constant VERIFIER_CUT_MIN = 5; + uint32 public constant VERIFIER_CUT_MAX = 100000; + uint64 public constant THAWING_PERIOD_MIN = 15; + uint64 public constant THAWING_PERIOD_MAX = 76; + + constructor(address controller) DataService(controller) initializer { + __DataService_init(); + } + + function register(address serviceProvider, bytes calldata data) external {} + + function acceptProvision(address serviceProvider, bytes calldata data) external {} + + function startService(address serviceProvider, bytes calldata data) external {} + + function stopService(address serviceProvider, bytes calldata data) external {} + + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + + function slash(address serviceProvider, bytes calldata data) external {} + + function setPauseGuardian(address pauseGuardian, bool allowed) external { + _setPauseGuardian(pauseGuardian, allowed); + } +} From 17d3b792c6541546db163c0121c72a63de0c89dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 12 Jun 2024 11:42:48 +0200 Subject: [PATCH 128/277] test: upgradeable contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../data-service/DataServiceUpgradeable.t.sol | 15 ++++-- .../data-service/DataServiceUpgradeable.tree | 3 -- .../DataServicePausableUpgradeable.t.sol | 54 +++++++++++++++++++ .../DataServiceBaseUpgradeable.sol | 4 ++ .../DataServiceImpPausableUpgradeable.sol | 33 ++++++++++++ 5 files changed, 102 insertions(+), 7 deletions(-) delete mode 100644 packages/horizon/test/data-service/DataServiceUpgradeable.tree create mode 100644 packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol create mode 100644 packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol index dff804a2b..7ff6c8246 100644 --- a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol +++ b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol @@ -6,9 +6,11 @@ import { DataServiceBaseUpgradeable } from "./implementations/DataServiceBaseUpg import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; contract DataServiceUpgradeableTest is GraphBaseTest { - function test_WhenTheContractIsDeployedWithAValidController() external { - DataServiceBaseUpgradeable dataService = _deployDataService(); + function test_WhenTheContractIsDeployed() external { + (DataServiceBaseUpgradeable dataService, DataServiceBaseUpgradeable implementation) = _deployDataService(); + // via proxy - ensure that the proxy was initialized correctly + // these calls validate proxy storage was correctly initialized uint32 delegationRatio = dataService.getDelegationRatio(); assertEq(delegationRatio, type(uint32).min); @@ -23,9 +25,14 @@ contract DataServiceUpgradeableTest is GraphBaseTest { (uint64 minThawingPeriod, uint64 maxThawingPeriod) = dataService.getThawingPeriodRange(); assertEq(minThawingPeriod, type(uint64).min); assertEq(maxThawingPeriod, type(uint64).max); + + // this ensures that implementation immutables were correctly initialized + // and they can be read via the proxy + assertEq(implementation.controller(), address(controller)); + assertEq(dataService.controller(), address(controller)); } - function _deployDataService() internal returns (DataServiceBaseUpgradeable) { + function _deployDataService() internal returns (DataServiceBaseUpgradeable, DataServiceBaseUpgradeable) { // Deploy implementation address implementation = address(new DataServiceBaseUpgradeable(address(controller))); @@ -36,6 +43,6 @@ contract DataServiceUpgradeableTest is GraphBaseTest { abi.encodeCall(DataServiceBaseUpgradeable.initialize, ()) ); - return DataServiceBaseUpgradeable(proxy); + return (DataServiceBaseUpgradeable(proxy), DataServiceBaseUpgradeable(implementation)); } } diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.tree b/packages/horizon/test/data-service/DataServiceUpgradeable.tree deleted file mode 100644 index dbb433635..000000000 --- a/packages/horizon/test/data-service/DataServiceUpgradeable.tree +++ /dev/null @@ -1,3 +0,0 @@ -DataServiceUpgradeableTest -└── when the contract is deployed with a valid controller - └── it should set all it's ranges to max \ No newline at end of file diff --git a/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol b/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol new file mode 100644 index 000000000..eef727465 --- /dev/null +++ b/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import { GraphBaseTest } from "../../GraphBase.t.sol"; +import { DataServiceImpPausableUpgradeable } from "../implementations/DataServiceImpPausableUpgradeable.sol"; +import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; + +contract DataServicePausableUpgradeableTest is GraphBaseTest { + function test_WhenTheContractIsDeployed() external { + ( + DataServiceImpPausableUpgradeable dataService, + DataServiceImpPausableUpgradeable implementation + ) = _deployDataService(); + + // via proxy - ensure that the proxy was initialized correctly + // these calls validate proxy storage was correctly initialized + uint32 delegationRatio = dataService.getDelegationRatio(); + assertEq(delegationRatio, type(uint32).min); + + (uint256 minTokens, uint256 maxTokens) = dataService.getProvisionTokensRange(); + assertEq(minTokens, type(uint256).min); + assertEq(maxTokens, type(uint256).max); + + (uint32 minVerifierCut, uint32 maxVerifierCut) = dataService.getVerifierCutRange(); + assertEq(minVerifierCut, type(uint32).min); + assertEq(maxVerifierCut, type(uint32).max); + + (uint64 minThawingPeriod, uint64 maxThawingPeriod) = dataService.getThawingPeriodRange(); + assertEq(minThawingPeriod, type(uint64).min); + assertEq(maxThawingPeriod, type(uint64).max); + + // this ensures that implementation immutables were correctly initialized + // and they can be read via the proxy + assertEq(implementation.controller(), address(controller)); + assertEq(dataService.controller(), address(controller)); + } + + function _deployDataService() + internal + returns (DataServiceImpPausableUpgradeable, DataServiceImpPausableUpgradeable) + { + // Deploy implementation + address implementation = address(new DataServiceImpPausableUpgradeable(address(controller))); + + // Deploy proxy + address proxy = UnsafeUpgrades.deployTransparentProxy( + implementation, + users.governor, + abi.encodeCall(DataServiceImpPausableUpgradeable.initialize, ()) + ); + + return (DataServiceImpPausableUpgradeable(proxy), DataServiceImpPausableUpgradeable(implementation)); + } +} diff --git a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol index 9913c1b76..af0f22aaf 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol @@ -24,4 +24,8 @@ contract DataServiceBaseUpgradeable is DataService { function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} function slash(address serviceProvider, bytes calldata data) external {} + + function controller() external view returns (address) { + return address(_graphController()); + } } diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol new file mode 100644 index 000000000..14b23bc9c --- /dev/null +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { DataService } from "../../../contracts/data-service/DataService.sol"; +import { DataServicePausableUpgradeable } from "../../../contracts/data-service/extensions/DataServicePausableUpgradeable.sol"; +import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; + +contract DataServiceImpPausableUpgradeable is DataServicePausableUpgradeable { + constructor(address controller) DataService(controller) { + _disableInitializers(); + } + + function initialize() external initializer { + __DataService_init(); + __DataServicePausable_init(); + } + + function register(address serviceProvider, bytes calldata data) external {} + + function acceptProvision(address serviceProvider, bytes calldata data) external {} + + function startService(address serviceProvider, bytes calldata data) external {} + + function stopService(address serviceProvider, bytes calldata data) external {} + + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + + function slash(address serviceProvider, bytes calldata data) external {} + + function controller() external view returns (address) { + return address(_graphController()); + } +} From 54c4a39419420df57ff038fb87435dc86c0bcb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 12 Jun 2024 11:52:17 +0200 Subject: [PATCH 129/277] test: more pausable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServicePausable.t.sol | 35 ++++++++++++++++--- .../extensions/DataServicePausable.tree | 14 +++++++- .../implementations/DataServiceFees.sol | 0 .../DataServiceImpPausable.sol | 11 ++++++ 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 packages/horizon/test/data-service/implementations/DataServiceFees.sol diff --git a/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol b/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol index e65f579f5..c71cace11 100644 --- a/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol @@ -1,10 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "forge-std/Test.sol"; -import {HorizonStakingSharedTest} from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; -import {DataServiceImpPausable} from "../implementations/DataServiceImpPausable.sol"; -import {IDataServicePausable} from "./../../../contracts/data-service/interfaces/IDataServicePausable.sol"; +import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; +import { DataServiceImpPausable } from "../implementations/DataServiceImpPausable.sol"; +import { IDataServicePausable } from "./../../../contracts/data-service/interfaces/IDataServicePausable.sol"; contract DataServicePausableTest is HorizonStakingSharedTest { DataServiceImpPausable dataService; @@ -71,6 +70,34 @@ contract DataServicePausableTest is HorizonStakingSharedTest { _assert_setPauseGuardian(address(this), false); } + function test_PausedProtectedFn_RevertWhen_TheProtocolIsPaused() external { + _assert_setPauseGuardian(address(this), true); + _assert_pause(); + + vm.expectRevert(abi.encodeWithSignature("EnforcedPause()")); + dataService.pausedProtectedFn(); + } + + function test_PausedProtectedFn_WhenTheProtocolIsNotPaused() external { + vm.expectEmit(); + emit DataServiceImpPausable.PausedProtectedFn(); + dataService.pausedProtectedFn(); + } + + function test_UnpausedProtectedFn_WhenTheProtocolIsPaused() external { + _assert_setPauseGuardian(address(this), true); + _assert_pause(); + + vm.expectEmit(); + emit DataServiceImpPausable.UnpausedProtectedFn(); + dataService.unpausedProtectedFn(); + } + + function test_UnpausedProtectedFn_RevertWhen_TheProtocolIsNotPaused() external { + vm.expectRevert(abi.encodeWithSignature("ExpectedPause()")); + dataService.unpausedProtectedFn(); + } + function _assert_pause() private { vm.expectEmit(); emit Paused(address(this)); diff --git a/packages/horizon/test/data-service/extensions/DataServicePausable.tree b/packages/horizon/test/data-service/extensions/DataServicePausable.tree index 9a3692026..1c162c55d 100644 --- a/packages/horizon/test/data-service/extensions/DataServicePausable.tree +++ b/packages/horizon/test/data-service/extensions/DataServicePausable.tree @@ -20,4 +20,16 @@ DataServicePausableTest::setPauseGuardian_ ├── when setting a pause guardian │ └── it should emit an event └── when removing a pause guardian - └── it should emit an event \ No newline at end of file + └── it should emit an event + +DataServicePausableTest::pausedProtectedFn_ +├── when the protocol is paused +│ └── it should revert +└── when the protocol is not paused + └── it should emit an event + +DataServicePausableTest::unpausedProtectedFn_ +├── when the protocol is paused +│ └── it should emit an event +└── when the protocol is not paused + └── it should revert diff --git a/packages/horizon/test/data-service/implementations/DataServiceFees.sol b/packages/horizon/test/data-service/implementations/DataServiceFees.sol new file mode 100644 index 000000000..e69de29bb diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol index ff40733b2..ad5308e33 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol @@ -14,6 +14,9 @@ contract DataServiceImpPausable is DataServicePausable { uint64 public constant THAWING_PERIOD_MIN = 15; uint64 public constant THAWING_PERIOD_MAX = 76; + event PausedProtectedFn(); + event UnpausedProtectedFn(); + constructor(address controller) DataService(controller) initializer { __DataService_init(); } @@ -33,4 +36,12 @@ contract DataServiceImpPausable is DataServicePausable { function setPauseGuardian(address pauseGuardian, bool allowed) external { _setPauseGuardian(pauseGuardian, allowed); } + + function pausedProtectedFn() external whenNotPaused { + emit PausedProtectedFn(); + } + + function unpausedProtectedFn() external whenPaused { + emit UnpausedProtectedFn(); + } } From 086a94c1516a7207319f35531cf92a44988b7482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 13 Jun 2024 17:45:13 +0200 Subject: [PATCH 130/277] test: add data service fees tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../extensions/DataServiceFees.sol | 1 + .../interfaces/IDataServiceFees.sol | 5 + .../extensions/DataServiceFees.t.sol | 220 ++++++++++++++++++ .../extensions/DataServiceFees.tree | 21 ++ .../implementations/DataServiceFees.sol | 0 .../implementations/DataServiceImpFees.sol | 35 +++ 6 files changed, 282 insertions(+) create mode 100644 packages/horizon/test/data-service/extensions/DataServiceFees.t.sol create mode 100644 packages/horizon/test/data-service/extensions/DataServiceFees.tree delete mode 100644 packages/horizon/test/data-service/implementations/DataServiceFees.sol create mode 100644 packages/horizon/test/data-service/implementations/DataServiceImpFees.sol diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index d9a6122b6..bcec6f828 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -39,6 +39,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat * @param _unlockTimestamp The timestamp when the tokens can be released */ function _lockStake(address _serviceProvider, uint256 _tokens, uint256 _unlockTimestamp) internal { + require(_tokens != 0, DataServiceFeesZeroTokens()); feesProvisionTracker.lock(_graphStaking(), _serviceProvider, _tokens, delegationRatio); LinkedList.List storage claimsList = claimsLists[_serviceProvider]; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index b730a09e6..5e84863e6 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -78,6 +78,11 @@ interface IDataServiceFees is IDataService { */ error DataServiceFeesClaimNotFound(bytes32 claimId); + /** + * @notice Emitted when trying to lock zero tokens in a stake claim + */ + error DataServiceFeesZeroTokens(); + /** * @notice Releases expired stake claims for the caller. * @dev This function is only meant to be called if the service provider has enough diff --git a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol new file mode 100644 index 000000000..8ad370c48 --- /dev/null +++ b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "forge-std/Console.sol"; +import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; +import { DataServiceImpFees } from "../implementations/DataServiceImpFees.sol"; +import { IDataServiceFees } from "../../../contracts/data-service/interfaces/IDataServiceFees.sol"; +import { ProvisionTracker } from "../../../contracts/data-service/libraries/ProvisionTracker.sol"; +import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; + +contract DataServiceFeesTest is HorizonStakingSharedTest { + function test_Lock_RevertWhen_ZeroTokensAreLocked() + external + useIndexer + useProvisionDataService(address(dataService), PROVISION_TOKENS, 0, 0) + { + vm.expectRevert(abi.encodeWithSignature("DataServiceFeesZeroTokens()")); + dataService.lockStake(users.indexer, 0); + } + + uint256 public constant PROVISION_TOKENS = 10_000_000 ether; + DataServiceImpFees dataService; + + function setUp() public override { + super.setUp(); + + dataService = new DataServiceImpFees(address(controller)); + } + + function test_Lock_WhenTheProvisionHasEnoughTokens( + uint256 tokens + ) external useIndexer useProvisionDataService(address(dataService), PROVISION_TOKENS, 0, 0) { + tokens = bound(tokens, 1, PROVISION_TOKENS / dataService.STAKE_TO_FEES_RATIO()); + + _assert_lockStake(users.indexer, tokens); + } + + function test_Lock_WhenTheProvisionHasJustEnoughTokens( + uint256 tokens, + uint256 steps + ) external useIndexer useProvisionDataService(address(dataService), PROVISION_TOKENS, 0, 0) { + // lock all provisioned stake in steps + // limit tokens to at least 1 per step + tokens = bound(tokens, 50, PROVISION_TOKENS / dataService.STAKE_TO_FEES_RATIO()); + steps = bound(steps, 1, 50); + uint256 stepAmount = tokens / steps; + + for (uint256 i = 0; i < steps; i++) { + _assert_lockStake(users.indexer, stepAmount); + } + + uint256 lockedStake = dataService.feesProvisionTracker(users.indexer); + uint256 delta = (tokens % steps); + assertEq(lockedStake, stepAmount * dataService.STAKE_TO_FEES_RATIO() * steps); + assertEq(tokens * dataService.STAKE_TO_FEES_RATIO() - lockedStake, delta * dataService.STAKE_TO_FEES_RATIO()); + } + + function test_Lock_RevertWhen_TheProvisionHasNotEnoughTokens( + uint256 tokens + ) external useIndexer useProvisionDataService(address(dataService), PROVISION_TOKENS, 0, 0) { + tokens = bound(tokens, 1, PROVISION_TOKENS / dataService.STAKE_TO_FEES_RATIO()); + + // lock everything + _assert_lockStake(users.indexer, PROVISION_TOKENS / dataService.STAKE_TO_FEES_RATIO()); + + // tryna lock some more + uint256 additionalTokens = 10000; + uint256 tokensRequired = dataService.feesProvisionTracker(users.indexer) + + additionalTokens * + dataService.STAKE_TO_FEES_RATIO(); + uint256 tokensAvailable = staking.getTokensAvailable(users.indexer, address(dataService), 0); + vm.expectRevert( + abi.encodeWithSelector( + ProvisionTracker.ProvisionTrackerInsufficientTokens.selector, + tokensAvailable, + tokensRequired + ) + ); + dataService.lockStake(users.indexer, additionalTokens); + } + + function test_Release_WhenNIsValid( + uint256 tokens, + uint256 steps, + uint256 n + ) external useIndexer useProvisionDataService(address(dataService), PROVISION_TOKENS, 0, 0) { + // lock all provisioned stake in steps + // limit tokens to at least 1 per step + // limit steps to at least 15 so we stagger locks every 5 seconds to have some expired + tokens = bound(tokens, 50, PROVISION_TOKENS / dataService.STAKE_TO_FEES_RATIO()); + steps = bound(steps, 15, 50); + n = bound(n, 0, steps); + + uint256 stepAmount = tokens / steps; + + // lock tokens staggering the release + for (uint256 i = 0; i < steps; i++) { + _assert_lockStake(users.indexer, stepAmount); + vm.warp(block.timestamp + 5 seconds); + } + + // it should release all expired claims + _assert_releaseStake(users.indexer, n); + } + + function test_Release_WhenNIsNotValid( + uint256 tokens, + uint256 steps + ) external useIndexer useProvisionDataService(address(dataService), PROVISION_TOKENS, 0, 0) { + // lock all provisioned stake in steps + // limit tokens to at least 1 per step + // limit steps to at least 15 so we stagger locks every 5 seconds to have some expired + tokens = bound(tokens, 50, PROVISION_TOKENS / dataService.STAKE_TO_FEES_RATIO()); + steps = bound(steps, 15, 50); + + uint256 stepAmount = tokens / steps; + + // lock tokens staggering the release + for (uint256 i = 0; i < steps; i++) { + _assert_lockStake(users.indexer, stepAmount); + vm.warp(block.timestamp + 5 seconds); + } + + // it should revert + vm.expectRevert(abi.encodeWithSelector(LinkedList.LinkedListInvalidIterations.selector)); + dataService.releaseStake(steps + 1); + } + + // -- Assertion functions -- + + function _assert_lockStake(address serviceProvider, uint256 tokens) private { + // before state + (bytes32 beforeHead, , uint256 beforeNonce, uint256 beforeCount) = dataService.claimsLists(serviceProvider); + uint256 beforeLockedStake = dataService.feesProvisionTracker(serviceProvider); + + // calc + uint256 unlockTimestamp = block.timestamp + dataService.LOCK_DURATION(); + uint256 stakeToLock = tokens * dataService.STAKE_TO_FEES_RATIO(); + bytes32 predictedClaimId = keccak256(abi.encodePacked(address(dataService), serviceProvider, beforeNonce)); + + // it should emit a an event + vm.expectEmit(); + emit IDataServiceFees.StakeClaimLocked(serviceProvider, predictedClaimId, stakeToLock, unlockTimestamp); + dataService.lockStake(serviceProvider, tokens); + + // after state + uint256 afterLockedStake = dataService.feesProvisionTracker(serviceProvider); + (bytes32 afterHead, bytes32 afterTail, uint256 afterNonce, uint256 afterCount) = dataService.claimsLists( + serviceProvider + ); + + // it should lock the tokens + assertEq(beforeLockedStake + stakeToLock, afterLockedStake); + + // it should create a stake claim + (uint256 claimTokens, uint256 createdAt, uint256 releaseAt, bytes32 nextClaim) = dataService.claims( + predictedClaimId + ); + assertEq(claimTokens, stakeToLock); + assertEq(createdAt, block.timestamp); + assertEq(releaseAt, unlockTimestamp); + assertEq(nextClaim, bytes32(0)); + + // it should update the list + assertEq(afterCount, beforeCount + 1); + assertEq(afterNonce, beforeNonce + 1); + assertEq(afterHead, beforeCount == 0 ? predictedClaimId : beforeHead); + assertEq(afterTail, predictedClaimId); + } + + function _assert_releaseStake(address serviceProvider, uint256 n) private { + // before state + (bytes32 beforeHead, bytes32 beforeTail, uint256 beforeNonce, uint256 beforeCount) = dataService.claimsLists( + serviceProvider + ); + uint256 beforeLockedStake = dataService.feesProvisionTracker(serviceProvider); + + // calc and set events + vm.expectEmit(); + + uint256 claimsCount = 0; + uint256 tokensReleased = 0; + bytes32 head = beforeHead; + while (head != bytes32(0) && (claimsCount < n || n == 0)) { + (uint256 claimTokens, , uint256 releaseAt, bytes32 nextClaim) = dataService.claims(head); + if (releaseAt > block.timestamp) { + break; + } + + emit IDataServiceFees.StakeClaimReleased(serviceProvider, head, claimTokens, releaseAt); + head = nextClaim; + tokensReleased += claimTokens; + claimsCount++; + } + + // it should emit a an event + emit IDataServiceFees.StakeClaimsReleased(serviceProvider, claimsCount, tokensReleased); + dataService.releaseStake(n); + + // after state + (bytes32 afterHead, bytes32 afterTail, uint256 afterNonce, uint256 afterCount) = dataService.claimsLists( + serviceProvider + ); + uint256 afterLockedStake = dataService.feesProvisionTracker(serviceProvider); + + // it should release the tokens + assertEq(beforeLockedStake - tokensReleased, afterLockedStake); + + // it should remove the processed claims from the list + assertEq(afterCount, beforeCount - claimsCount); + assertEq(afterNonce, beforeNonce); + if (claimsCount != 0) { + assertNotEq(afterHead, beforeHead); + } else { + assertEq(afterHead, beforeHead); + } + assertEq(afterHead, head); + assertEq(afterTail, claimsCount == beforeCount ? bytes32(0) : beforeTail); + } +} diff --git a/packages/horizon/test/data-service/extensions/DataServiceFees.tree b/packages/horizon/test/data-service/extensions/DataServiceFees.tree new file mode 100644 index 000000000..331627179 --- /dev/null +++ b/packages/horizon/test/data-service/extensions/DataServiceFees.tree @@ -0,0 +1,21 @@ +DataServiceFeesTest::lock_ +├── when zero tokens are locked +│ └── it should revert +├── when the provision has enough tokens +│ ├── it should lock the tokens +│ ├── it should create a stake claim +│ ├── it should update the claims list +│ └── it should emit a an event +├── when the provision has just enough tokens +│ ├── it should lock the tokens +│ ├── it should create a stake claim +│ ├── it should update the claims list +│ └── it should emit a an event +└──when the provision has not enough tokens + └── it should revert + +DataServiceFeesTest::release_ +├── when n is valid +│ └── it should release all expired claims +└── when n is not valid + └── it should release at most n expired claims \ No newline at end of file diff --git a/packages/horizon/test/data-service/implementations/DataServiceFees.sol b/packages/horizon/test/data-service/implementations/DataServiceFees.sol deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol new file mode 100644 index 000000000..72574cedb --- /dev/null +++ b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.26; + +import { DataService } from "../../../contracts/data-service/DataService.sol"; +import { DataServiceFees } from "../../../contracts/data-service/extensions/DataServiceFees.sol"; +import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; + +contract DataServiceImpFees is DataServiceFees { + uint256 public constant STAKE_TO_FEES_RATIO = 1000; + uint256 public constant LOCK_DURATION = 1 minutes; + + constructor(address controller) DataService(controller) initializer { + __DataService_init(); + } + + function register(address serviceProvider, bytes calldata data) external {} + + function acceptProvision(address serviceProvider, bytes calldata data) external {} + + function startService(address serviceProvider, bytes calldata data) external {} + + function stopService(address serviceProvider, bytes calldata data) external {} + + function collect(address serviceProvider, IGraphPayments.PaymentTypes, bytes calldata data) external { + uint256 amount = abi.decode(data, (uint256)); + _releaseStake(serviceProvider, 0); + _lockStake(serviceProvider, amount * STAKE_TO_FEES_RATIO, block.timestamp + LOCK_DURATION); + } + + function lockStake(address serviceProvider, uint256 amount) external { + _lockStake(serviceProvider, amount * STAKE_TO_FEES_RATIO, block.timestamp + LOCK_DURATION); + } + + function slash(address serviceProvider, bytes calldata data) external {} +} From 6627b7d61e3111a0181d9e0a3ab6269b0fba5d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 14 Jun 2024 09:41:34 +0200 Subject: [PATCH 131/277] fix: remove console import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../horizon/test/data-service/extensions/DataServiceFees.t.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol index 8ad370c48..4ab1406ae 100644 --- a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "forge-std/Console.sol"; import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; import { DataServiceImpFees } from "../implementations/DataServiceImpFees.sol"; import { IDataServiceFees } from "../../../contracts/data-service/interfaces/IDataServiceFees.sol"; From c4b49583e5f5b7df7898074d44eb7b70e13ac795 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 18 Jun 2024 18:34:57 -0300 Subject: [PATCH 132/277] chore: refactor dispute manager tests --- .../test/DisputeManager.t.sol | 512 ------------------ .../subgraph-service/test/GraphBaseTest.t.sol | 123 +++++ .../test/disputes/DisputeManager.t.sol | 128 +++++ .../test/disputes/accept.t.sol | 126 +++++ .../test/disputes/cancel.t.sol | 74 +++ .../test/disputes/create.t.sol | 157 ++++++ .../subgraph-service/test/disputes/draw.t.sol | 71 +++ .../test/mocks/MockHorizonStaking.sol | 4 +- .../subgraph-service/test/utils/Constants.sol | 13 + .../subgraph-service/test/utils/Users.sol | 14 + .../subgraph-service/test/utils/Utils.sol | 12 + 11 files changed, 720 insertions(+), 514 deletions(-) delete mode 100644 packages/subgraph-service/test/DisputeManager.t.sol create mode 100644 packages/subgraph-service/test/GraphBaseTest.t.sol create mode 100644 packages/subgraph-service/test/disputes/DisputeManager.t.sol create mode 100644 packages/subgraph-service/test/disputes/accept.t.sol create mode 100644 packages/subgraph-service/test/disputes/cancel.t.sol create mode 100644 packages/subgraph-service/test/disputes/create.t.sol create mode 100644 packages/subgraph-service/test/disputes/draw.t.sol create mode 100644 packages/subgraph-service/test/utils/Constants.sol create mode 100644 packages/subgraph-service/test/utils/Users.sol create mode 100644 packages/subgraph-service/test/utils/Utils.sol diff --git a/packages/subgraph-service/test/DisputeManager.t.sol b/packages/subgraph-service/test/DisputeManager.t.sol deleted file mode 100644 index a5375dc0d..000000000 --- a/packages/subgraph-service/test/DisputeManager.t.sol +++ /dev/null @@ -1,512 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; -import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; -import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; - -import { DisputeManager } from "../contracts/DisputeManager.sol"; -import { IDisputeManager } from "../contracts/interfaces/IDisputeManager.sol"; -import { Attestation } from "../contracts/libraries/Attestation.sol"; - -import { SubgraphService } from "../contracts/SubgraphService.sol"; - -// Mocks - -import "./mocks/MockGRTToken.sol"; -import "./mocks/MockHorizonStaking.sol"; -import "./mocks/MockRewardsManager.sol"; - -contract DisputeManagerTest is Test { - DisputeManager disputeManager; - - address governor; - address arbitrator; - - uint256 indexerPrivateKey; - address indexer; - - uint256 fishermanPrivateKey; - address fisherman; - - uint256 allocationIDPrivateKey; - address allocationID; - - uint64 disputePeriod = 300; // 5 minutes - uint256 minimumDeposit = 100 ether; // 100 GRT - uint32 fishermanRewardPercentage = 100000; // 10% - uint32 maxSlashingPercentage = 500000; // 50% - - Controller controller; - MockGRTToken graphToken; - SubgraphService subgraphService; - MockHorizonStaking staking; - MockRewardsManager rewardsManager; - - // Setup - - function setUp() public { - governor = address(0xA1); - arbitrator = address(0xA2); - - indexerPrivateKey = 0xB1; - indexer = vm.addr(indexerPrivateKey); - - fishermanPrivateKey = 0xC1; - fisherman = vm.addr(fishermanPrivateKey); - - allocationIDPrivateKey = 0xD1; - allocationID = vm.addr(allocationIDPrivateKey); - - graphToken = new MockGRTToken(); - staking = new MockHorizonStaking(address(graphToken)); - rewardsManager = new MockRewardsManager(); - - address tapVerifier = address(0xE3); - address curation = address(0xE4); - - vm.startPrank(governor); - controller = new Controller(); - controller.setContractProxy(keccak256("GraphToken"), address(graphToken)); - controller.setContractProxy(keccak256("Staking"), address(staking)); - controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); - controller.setContractProxy(keccak256("GraphPayments"), address(0x100)); - controller.setContractProxy(keccak256("PaymentsEscrow"), address(0x101)); - controller.setContractProxy(keccak256("EpochManager"), address(0x102)); - controller.setContractProxy(keccak256("GraphTokenGateway"), address(0x103)); - controller.setContractProxy(keccak256("GraphProxyAdmin"), address(0x104)); - controller.setContractProxy(keccak256("Curation"), address(0x105)); - vm.stopPrank(); - - address disputeManagerImplementation = address(new DisputeManager(address(controller))); - address disputeManagerProxy = UnsafeUpgrades.deployTransparentProxy( - disputeManagerImplementation, - governor, - abi.encodeCall( - DisputeManager.initialize, - (arbitrator, disputePeriod, minimumDeposit, fishermanRewardPercentage, maxSlashingPercentage) - ) - ); - disputeManager = DisputeManager(disputeManagerProxy); - - address subgraphServiceImplementation = address( - new SubgraphService(address(controller), address(disputeManager), tapVerifier, curation) - ); - address subgraphServiceProxy = UnsafeUpgrades.deployTransparentProxy( - subgraphServiceImplementation, - governor, - abi.encodeCall(SubgraphService.initialize, (1000 ether, 16)) - ); - subgraphService = SubgraphService(subgraphServiceProxy); - - disputeManager.setSubgraphService(address(subgraphService)); - } - - // Helper functions - - function createProvisionAndAllocate(address _allocationID, uint256 tokens) private { - vm.startPrank(indexer); - graphToken.mint(indexer, tokens); - staking.provision(tokens, address(subgraphService), 500000, 300); - bytes32 subgraphDeployment = keccak256(abi.encodePacked("Subgraph Deployment ID")); - bytes32 digest = subgraphService.encodeAllocationProof(indexer, _allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - - subgraphService.register(indexer, abi.encode("url", "geoHash", address(0))); - - bytes memory data = abi.encode(subgraphDeployment, tokens, _allocationID, abi.encodePacked(r, s, v)); - subgraphService.startService(indexer, data); - vm.stopPrank(); - } - - function createIndexingDispute(address _allocationID, bytes32 _poi, uint256 tokens) private returns (bytes32 disputeID) { - vm.startPrank(fisherman); - graphToken.mint(fisherman, tokens); - graphToken.approve(address(disputeManager), tokens); - bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, _poi, tokens); - vm.stopPrank(); - return _disputeID; - } - - function createQueryDispute(uint256 tokens) private returns (bytes32 disputeID) { - Attestation.Receipt memory receipt = Attestation.Receipt({ - requestCID: keccak256(abi.encodePacked("Request CID")), - responseCID: keccak256(abi.encodePacked("Response CID")), - subgraphDeploymentId: keccak256(abi.encodePacked("Subgraph Deployment ID")) - }); - bytes memory attestationData = createAtestationData(receipt, allocationIDPrivateKey); - - vm.startPrank(fisherman); - graphToken.mint(fisherman, tokens); - graphToken.approve(address(disputeManager), tokens); - bytes32 _disputeID = disputeManager.createQueryDispute(attestationData, tokens); - vm.stopPrank(); - return _disputeID; - } - - function createConflictingAttestations( - bytes32 responseCID1, - bytes32 subgraphDeploymentId1, - bytes32 responseCID2, - bytes32 subgraphDeploymentId2 - ) private view returns (bytes memory attestationData1, bytes memory attestationData2) { - bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); - Attestation.Receipt memory receipt1 = Attestation.Receipt({ - requestCID: requestCID, - responseCID: responseCID1, - subgraphDeploymentId: subgraphDeploymentId1 - }); - - Attestation.Receipt memory receipt2 = Attestation.Receipt({ - requestCID: requestCID, - responseCID: responseCID2, - subgraphDeploymentId: subgraphDeploymentId2 - }); - - bytes memory _attestationData1 = createAtestationData(receipt1, allocationIDPrivateKey); - bytes memory _attestationData2 = createAtestationData(receipt2, allocationIDPrivateKey); - return (_attestationData1, _attestationData2); - } - - function createAtestationData( - Attestation.Receipt memory receipt, - uint256 signer - ) private view returns (bytes memory attestationData) { - bytes32 digest = disputeManager.encodeReceipt(receipt); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); - - return abi.encodePacked(receipt.requestCID, receipt.responseCID, receipt.subgraphDeploymentId, r, s, v); - } - - // Tests - - // Create dispute - - function testCreateIndexingDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); - assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); - } - - function testCreateQueryDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - - bytes32 disputeID = createQueryDispute(200 ether); - assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); - } - - function testCreateQueryDisputeConflict() public { - createProvisionAndAllocate(allocationID, 10000 ether); - - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - assertTrue(disputeManager.isDisputeCreated(disputeID1), "Dispute 1 should be created."); - assertTrue(disputeManager.isDisputeCreated(disputeID2), "Dispute 2 should be created."); - } - - function test_RevertWhen_DisputeAlreadyCreated() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); - - // Create another dispute with different fisherman - address otherFisherman = address(0x5); - uint256 tokens = 200 ether; - vm.startPrank(otherFisherman); - graphToken.mint(otherFisherman, tokens); - graphToken.approve(address(disputeManager), tokens); - bytes memory expectedError = abi.encodeWithSignature("DisputeManagerDisputeAlreadyCreated(bytes32)", disputeID); - vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI1"), tokens); - vm.stopPrank(); - } - - function test_RevertIf_DepositUnderMinimum() public { - // minimum deposit is 100 ether - vm.startPrank(fisherman); - graphToken.mint(fisherman, 50 ether); - bytes memory expectedError = abi.encodeWithSignature( - "DisputeManagerInsufficientDeposit(uint256,uint256)", - 50 ether, - 100 ether - ); - vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI3"), 50 ether); - vm.stopPrank(); - } - - function test_RevertIf_AllocationDoesNotExist() public { - // create dispute without an existing allocation - uint256 tokens = 200 ether; - vm.startPrank(fisherman); - graphToken.mint(fisherman, tokens); - graphToken.approve(address(disputeManager), tokens); - bytes memory expectedError = abi.encodeWithSignature("DisputeManagerIndexerNotFound(address)", allocationID); - vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI4"), tokens); - vm.stopPrank(); - } - - function test_RevertIf_ConflictingAttestationsResponsesAreTheSame() public { - bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); - bytes32 responseCID = keccak256(abi.encodePacked("Response CID")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( - responseCID, - subgraphDeploymentId, - responseCID, - subgraphDeploymentId - ); - - vm.prank(fisherman); - - bytes memory expectedError = abi.encodeWithSignature( - "DisputeManagerNonConflictingAttestations(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32)", - requestCID, - responseCID, - subgraphDeploymentId, - requestCID, - responseCID, - subgraphDeploymentId - ); - vm.expectRevert(expectedError); - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); - } - - function test_RevertIf_ConflictingAttestationsHaveDifferentSubgraph() public { - bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId1 = keccak256(abi.encodePacked("Subgraph Deployment ID 1")); - bytes32 subgraphDeploymentId2 = keccak256(abi.encodePacked("Subgraph Deployment ID 2")); - - (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( - responseCID1, - subgraphDeploymentId1, - responseCID2, - subgraphDeploymentId2 - ); - - vm.prank(fisherman); - bytes memory expectedError = abi.encodeWithSignature( - "DisputeManagerNonConflictingAttestations(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32)", - requestCID, - responseCID1, - subgraphDeploymentId1, - requestCID, - responseCID2, - subgraphDeploymentId2 - ); - vm.expectRevert(expectedError); - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); - } - - // Accept dispute - - function testAcceptIndexingDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); - - vm.prank(arbitrator); - disputeManager.acceptDispute(disputeID, 5000 ether); - - assertEq(graphToken.balanceOf(fisherman), 700 ether, "Fisherman should receive 50% of slashed tokens."); - assertEq(graphToken.balanceOf(indexer), 5000 ether, "Service provider should have 5000 GRT slashed."); - } - - function testAcceptQueryDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createQueryDispute(200 ether); - - vm.prank(arbitrator); - disputeManager.acceptDispute(disputeID, 5000 ether); - - assertEq(graphToken.balanceOf(fisherman), 700 ether, "Fisherman should receive 50% of slashed tokens."); - assertEq(graphToken.balanceOf(indexer), 5000 ether, "Service provider should have 5000 GRT slashed."); - } - - function testAcceptQueryDisputeConflicting() public { - createProvisionAndAllocate(allocationID, 10000 ether); - - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - - vm.prank(arbitrator); - disputeManager.acceptDispute(disputeID1, 5000 ether); - - assertEq(graphToken.balanceOf(fisherman), 500 ether, "Fisherman should receive 50% of slashed tokens."); - assertEq(graphToken.balanceOf(indexer), 5000 ether, "Service provider should have 5000 GRT slashed."); - - (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); - assertTrue(status1 == IDisputeManager.DisputeStatus.Accepted, "Dispute 1 should be accepted."); - assertTrue(status2 == IDisputeManager.DisputeStatus.Rejected, "Dispute 2 should be rejected."); - } - - function test_RevertIf_CallerIsNotArbitrator_AcceptDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); - - // attempt to accept dispute as fisherman - vm.prank(fisherman); - vm.expectRevert(bytes4(keccak256("DisputeManagerNotArbitrator()"))); - disputeManager.acceptDispute(disputeID, 5000 ether); - } - - function test_RevertIf_SlashingOverMaxSlashPercentage() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI101"), 200 ether); - - // max slashing percentage is 50% - vm.prank(arbitrator); - bytes memory expectedError = abi.encodeWithSignature("DisputeManagerInvalidTokensSlash(uint256)", 6000 ether); - vm.expectRevert(expectedError); - disputeManager.acceptDispute(disputeID, 6000 ether); - } - - // Cancel dispute - - function testCancelDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); - - // skip to end of dispute period - skip(disputePeriod + 1); - - vm.prank(fisherman); - disputeManager.cancelDispute(disputeID); - - assertEq(graphToken.balanceOf(fisherman), 200 ether, "Fisherman should receive their deposit back."); - assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); - } - - function testCancelQueryDisputeConflicting() public { - createProvisionAndAllocate(allocationID, 10000 ether); - - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - - // skip to end of dispute period - skip(disputePeriod + 1); - - vm.prank(fisherman); - disputeManager.cancelDispute(disputeID1); - - assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); - - (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); - assertTrue(status1 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 1 should be cancelled."); - assertTrue(status2 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 2 should be cancelled."); - } - - function test_RevertIf_CallerIsNotFisherman_CancelDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI1"), 200 ether); - - vm.prank(arbitrator); - vm.expectRevert(bytes4(keccak256("DisputeManagerNotFisherman()"))); - disputeManager.cancelDispute(disputeID); - } - - // Draw dispute - - function testDrawDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID, bytes32("POI32"), 200 ether); - - vm.prank(arbitrator); - disputeManager.drawDispute(disputeID); - - assertEq(graphToken.balanceOf(fisherman), 200 ether, "Fisherman should receive their deposit back."); - assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); - } - - function testDrawQueryDisputeConflicting() public { - createProvisionAndAllocate(allocationID, 10000 ether); - - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - vm.prank(fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - - vm.prank(arbitrator); - disputeManager.drawDispute(disputeID1); - - assertEq(graphToken.balanceOf(indexer), 10000 ether, "There's no slashing to the indexer."); - - (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); - assertTrue(status1 == IDisputeManager.DisputeStatus.Drawn, "Dispute 1 should be drawn."); - assertTrue(status2 == IDisputeManager.DisputeStatus.Drawn, "Dispute 2 should be drawn."); - } - - function test_RevertIf_CallerIsNotArbitrator_DrawDispute() public { - createProvisionAndAllocate(allocationID, 10000 ether); - bytes32 disputeID = createIndexingDispute(allocationID,bytes32("POI1"), 200 ether); - - // attempt to draw dispute as fisherman - vm.prank(fisherman); - vm.expectRevert(bytes4(keccak256("DisputeManagerNotArbitrator()"))); - disputeManager.drawDispute(disputeID); - } -} diff --git a/packages/subgraph-service/test/GraphBaseTest.t.sol b/packages/subgraph-service/test/GraphBaseTest.t.sol new file mode 100644 index 000000000..4bf253e94 --- /dev/null +++ b/packages/subgraph-service/test/GraphBaseTest.t.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; +import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; + +import { SubgraphService } from "../contracts/SubgraphService.sol"; +import { DisputeManager } from "../contracts/DisputeManager.sol"; +import { Users } from "./utils/Users.sol"; +import { Constants } from "./utils/Constants.sol"; +import { Utils } from "./utils/Utils.sol"; + +import { MockGRTToken } from "./mocks/MockGRTToken.sol"; +import { MockHorizonStaking } from "./mocks/MockHorizonStaking.sol"; +import { MockRewardsManager } from "./mocks/MockRewardsManager.sol"; + +abstract contract GraphBaseTest is Utils, Constants { + + /* + * VARIABLES + */ + + /* Contracts */ + + Controller controller; + SubgraphService subgraphService; + DisputeManager disputeManager; + + MockGRTToken token; + MockHorizonStaking staking; + MockRewardsManager rewardsManager; + + /* Users */ + + Users internal users; + + /* + * SET UP + */ + + function setUp() public virtual { + token = new MockGRTToken(); + + // Setup Users + users = Users({ + governor: createUser("governor"), + deployer: createUser("deployer"), + indexer: createUser("indexer"), + operator: createUser("operator"), + gateway: createUser("gateway"), + verifier: createUser("verifier"), + delegator: createUser("delegator"), + arbitrator: createUser("arbitrator"), + fisherman: createUser("fisherman") + }); + + deployProtocolContracts(); + vm.stopPrank(); + } + + function deployProtocolContracts() private { + changePrank(users.deployer); + staking = new MockHorizonStaking(address(token)); + rewardsManager = new MockRewardsManager(); + + address tapVerifier = address(0xE3); + address curation = address(0xE4); + + changePrank(users.governor); + controller = new Controller(); + controller.setContractProxy(keccak256("GraphToken"), address(token)); + controller.setContractProxy(keccak256("Staking"), address(staking)); + controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); + controller.setContractProxy(keccak256("GraphPayments"), makeAddr("GraphPayments")); + controller.setContractProxy(keccak256("PaymentsEscrow"), makeAddr("PaymentsEscrow")); + controller.setContractProxy(keccak256("EpochManager"), makeAddr("EpochManager")); + controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); + controller.setContractProxy(keccak256("GraphProxyAdmin"), makeAddr("GraphProxyAdmin")); + controller.setContractProxy(keccak256("Curation"), makeAddr("Curation")); + + changePrank(users.deployer); + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + address disputeManagerProxy = UnsafeUpgrades.deployTransparentProxy( + disputeManagerImplementation, + users.governor, + abi.encodeCall( + DisputeManager.initialize, + (users.arbitrator, disputePeriod, minimumDeposit, fishermanRewardPercentage, maxSlashingPercentage) + ) + ); + disputeManager = DisputeManager(disputeManagerProxy); + + address subgraphServiceImplementation = address( + new SubgraphService(address(controller), address(disputeManager), tapVerifier, curation) + ); + address subgraphServiceProxy = UnsafeUpgrades.deployTransparentProxy( + subgraphServiceImplementation, + users.governor, + abi.encodeCall(SubgraphService.initialize, (minimumProvisionTokens, delegationRatio)) + ); + subgraphService = SubgraphService(subgraphServiceProxy); + + disputeManager.setSubgraphService(address(subgraphService)); + } + + function createUser(string memory name) private returns (address) { + address user = makeAddr(name); + vm.deal({ account: user, newBalance: 100 ether }); + deal({ token: address(token), to: user, give: 10_000_000_000 ether }); + vm.label({ account: user, newLabel: name }); + return user; + } + + function mint(address _address, uint256 amount) internal { + deal({ token: address(token), to: _address, give: amount }); + } + + function burn(address _from, uint256 amount) internal { + token.burnFrom(_from, amount); + } +} \ No newline at end of file diff --git a/packages/subgraph-service/test/disputes/DisputeManager.t.sol b/packages/subgraph-service/test/disputes/DisputeManager.t.sol new file mode 100644 index 000000000..cf50ab122 --- /dev/null +++ b/packages/subgraph-service/test/disputes/DisputeManager.t.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; +import { Attestation } from "../../contracts/libraries/Attestation.sol"; + +import { GraphBaseTest } from "../GraphBaseTest.t.sol"; + +contract DisputeManagerTest is GraphBaseTest { + using PPMMath for uint256; + + /* + * VARIABLES + */ + + uint256 allocationIDPrivateKey; + address allocationID; + + /* + * MODIFIERS + */ + + modifier useIndexer { + vm.startPrank(users.indexer); + _; + vm.stopPrank(); + } + + modifier useFisherman { + vm.startPrank(users.fisherman); + _; + vm.stopPrank(); + } + + modifier useProvision(uint256 tokens) { + vm.assume(tokens > minimumProvisionTokens); + vm.assume(tokens < 10_000_000_000 ether); + staking.provision(tokens, address(subgraphService), maxSlashingPercentage, disputePeriod); + bytes32 subgraphDeployment = keccak256(abi.encodePacked("Subgraph Deployment ID")); + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + + subgraphService.register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + subgraphService.startService(users.indexer, data); + _; + } + + /* + * SET UP + */ + + function setUp() public override { + super.setUp(); + (allocationID, allocationIDPrivateKey) = makeAddrAndKey("allocationId"); + } + + /* + * HELPERS + */ + + function _createIndexingDispute(address _allocationID, bytes32 _poi, uint256 tokens) internal returns (bytes32 disputeID) { + address msgSender; + (, msgSender,) = vm.readCallers(); + resetPrank(users.fisherman); + token.approve(address(disputeManager), tokens); + bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, _poi, tokens); + resetPrank(msgSender); + return _disputeID; + } + + function _createQueryDispute(uint256 tokens) internal returns (bytes32 disputeID) { + address msgSender; + (, msgSender,) = vm.readCallers(); + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = Attestation.Receipt({ + requestCID: keccak256(abi.encodePacked("Request CID")), + responseCID: keccak256(abi.encodePacked("Response CID")), + subgraphDeploymentId: keccak256(abi.encodePacked("Subgraph Deployment ID")) + }); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + + token.approve(address(disputeManager), tokens); + bytes32 _disputeID = disputeManager.createQueryDispute(attestationData, tokens); + resetPrank(msgSender); + return _disputeID; + } + + function _createConflictingAttestations( + bytes32 responseCID1, + bytes32 subgraphDeploymentId1, + bytes32 responseCID2, + bytes32 subgraphDeploymentId2 + ) internal view returns (bytes memory attestationData1, bytes memory attestationData2) { + bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); + Attestation.Receipt memory receipt1 = Attestation.Receipt({ + requestCID: requestCID, + responseCID: responseCID1, + subgraphDeploymentId: subgraphDeploymentId1 + }); + + Attestation.Receipt memory receipt2 = Attestation.Receipt({ + requestCID: requestCID, + responseCID: responseCID2, + subgraphDeploymentId: subgraphDeploymentId2 + }); + + bytes memory _attestationData1 = _createAtestationData(receipt1, allocationIDPrivateKey); + bytes memory _attestationData2 = _createAtestationData(receipt2, allocationIDPrivateKey); + return (_attestationData1, _attestationData2); + } + + function _createAtestationData( + Attestation.Receipt memory receipt, + uint256 signer + ) private view returns (bytes memory attestationData) { + bytes32 digest = disputeManager.encodeReceipt(receipt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); + + return abi.encodePacked(receipt.requestCID, receipt.responseCID, receipt.subgraphDeploymentId, r, s, v); + } +} diff --git a/packages/subgraph-service/test/disputes/accept.t.sol b/packages/subgraph-service/test/disputes/accept.t.sol new file mode 100644 index 000000000..52b3f21ec --- /dev/null +++ b/packages/subgraph-service/test/disputes/accept.t.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "./DisputeManager.t.sol"; + +contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { + using PPMMath for uint256; + + /* + * TESTS + */ + + function testAccept_IndexingDispute( + uint256 tokens, + uint256 tokensDispute, + uint256 tokensSlash + ) public useIndexer useProvision(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + + uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + + resetPrank(users.arbitrator); + disputeManager.acceptDispute(disputeID, tokensSlash); + + uint256 fishermanReward = tokensSlash.mulPPM(fishermanRewardPercentage); + uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; + assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance, "Fisherman should receive 50% of slashed tokens."); + } + + function testAccept_QueryDispute( + uint256 tokens, + uint256 tokensDispute, + uint256 tokensSlash + ) public useIndexer useProvision(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + + uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); + bytes32 disputeID = _createQueryDispute(tokensDispute); + + resetPrank(users.arbitrator); + disputeManager.acceptDispute(disputeID, tokensSlash); + + uint256 fishermanReward = tokensSlash.mulPPM(fishermanRewardPercentage); + uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; + assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance, "Fisherman should receive 50% of slashed tokens."); + } + + function testAccept_QueryDisputeConflicting( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useProvision(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); + + resetPrank(users.arbitrator); + disputeManager.acceptDispute(disputeID1, tokensSlash); + + uint256 fishermanReward = tokensSlash.mulPPM(fishermanRewardPercentage); + uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; + assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance, "Fisherman should receive 50% of slashed tokens."); + + (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + assertTrue(status1 == IDisputeManager.DisputeStatus.Accepted, "Dispute 1 should be accepted."); + assertTrue(status2 == IDisputeManager.DisputeStatus.Rejected, "Dispute 2 should be rejected."); + } + + function testAccept_RevertIf_CallerIsNotArbitrator( + uint256 tokens, + uint256 tokensDispute, + uint256 tokensSlash + ) public useIndexer useProvision(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + + // attempt to accept dispute as fisherman + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.acceptDispute(disputeID, tokensSlash); + } + + function testAccept_RevertWhen_SlashingOverMaxSlashPercentage( + uint256 tokens, + uint256 tokensDispute, + uint256 tokensSlash + ) public useIndexer useProvision(tokens) { + tokensSlash = bound(tokensSlash, uint256(maxSlashingPercentage).mulPPM(tokens) + 1, type(uint256).max); + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI101"), tokensDispute); + + // max slashing percentage is 50% + resetPrank(users.arbitrator); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidTokensSlash.selector, + tokensSlash + ); + vm.expectRevert(expectedError); + disputeManager.acceptDispute(disputeID, tokensSlash); + } +} diff --git a/packages/subgraph-service/test/disputes/cancel.t.sol b/packages/subgraph-service/test/disputes/cancel.t.sol new file mode 100644 index 000000000..db553a18b --- /dev/null +++ b/packages/subgraph-service/test/disputes/cancel.t.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "./DisputeManager.t.sol"; + +contract DisputeManagerCancelDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function testCancel_Dispute( + uint256 tokens, + uint256 tokensDispute + ) public useIndexer useProvision(tokens) { + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + + // skip to end of dispute period + skip(disputePeriod + 1); + + resetPrank(users.fisherman); + disputeManager.cancelDispute(disputeID); + + assertEq(token.balanceOf(users.fisherman), fishermanPreviousBalance, "Fisherman should receive their deposit back."); + } + + function testCancel_QueryDisputeConflicting( + uint256 tokens + ) public useIndexer useProvision(tokens) { + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); + + // skip to end of dispute period + skip(disputePeriod + 1); + + disputeManager.cancelDispute(disputeID1); + + (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + assertTrue(status1 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 1 should be cancelled."); + assertTrue(status2 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 2 should be cancelled."); + } + + function testCancel_RevertIf_CallerIsNotFisherman( + uint256 tokens, + uint256 tokensDispute + ) public useIndexer useProvision(tokens) { + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + + resetPrank(users.arbitrator); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotFisherman.selector)); + disputeManager.cancelDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputes/create.t.sol b/packages/subgraph-service/test/disputes/create.t.sol new file mode 100644 index 000000000..058eee21c --- /dev/null +++ b/packages/subgraph-service/test/disputes/create.t.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "./DisputeManager.t.sol"; + +contract DisputeManagerCreateDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function testCreate_IndexingDispute( + uint256 tokens, + uint256 tokensDispute + ) public useIndexer useProvision(tokens) { + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); + } + + function testCreate_QueryDispute( + uint256 tokens, + uint256 tokensDispute + ) public useIndexer useProvision(tokens) { + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + bytes32 disputeID = _createQueryDispute(tokensDispute); + assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); + } + + function testCreate_QueryDisputeConflict( + uint256 tokens + ) public useIndexer useProvision(tokens) { + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); + assertTrue(disputeManager.isDisputeCreated(disputeID1), "Dispute 1 should be created."); + assertTrue(disputeManager.isDisputeCreated(disputeID2), "Dispute 2 should be created."); + } + + function testCreate_RevertWhen_DisputeAlreadyCreated( + uint256 tokens, + uint256 tokensDispute + ) public useIndexer useProvision(tokens) { + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + + // Create another dispute with different fisherman + address otherFisherman = makeAddr("otherFisherman"); + resetPrank(otherFisherman); + mint(otherFisherman, tokensDispute); + token.approve(address(disputeManager), tokensDispute); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerDisputeAlreadyCreated.selector, + disputeID + ); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + vm.stopPrank(); + } + + function testCreate_RevertIf_DepositUnderMinimum( + uint256 tokensDispute + ) public useFisherman { + tokensDispute = bound(tokensDispute, 1, minimumDeposit - 1); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInsufficientDeposit.selector, + tokensDispute, + minimumDeposit + ); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, bytes32("POI3"), tokensDispute); + vm.stopPrank(); + } + + function testCreate_RevertIf_AllocationDoesNotExist( + uint256 tokens + ) public useFisherman { + tokens = bound(tokens, minimumDeposit, 10_000_000_000 ether); + token.approve(address(disputeManager), tokens); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerIndexerNotFound.selector, + allocationID + ); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, bytes32("POI4"), tokens); + vm.stopPrank(); + } + + function testCreate_RevertIf_ConflictingAttestationsResponsesAreTheSame() public useFisherman { + bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 responseCID = keccak256(abi.encodePacked("Response CID")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + responseCID, + subgraphDeploymentId, + responseCID, + subgraphDeploymentId + ); + + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerNonConflictingAttestations.selector, + requestCID, + responseCID, + subgraphDeploymentId, + requestCID, + responseCID, + subgraphDeploymentId + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + } + + function testCreate_RevertIf_ConflictingAttestationsHaveDifferentSubgraph() public { + bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId1 = keccak256(abi.encodePacked("Subgraph Deployment ID 1")); + bytes32 subgraphDeploymentId2 = keccak256(abi.encodePacked("Subgraph Deployment ID 2")); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + responseCID1, + subgraphDeploymentId1, + responseCID2, + subgraphDeploymentId2 + ); + + vm.prank(users.fisherman); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerNonConflictingAttestations.selector, + requestCID, + responseCID1, + subgraphDeploymentId1, + requestCID, + responseCID2, + subgraphDeploymentId2 + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + } +} diff --git a/packages/subgraph-service/test/disputes/draw.t.sol b/packages/subgraph-service/test/disputes/draw.t.sol new file mode 100644 index 000000000..0139bf929 --- /dev/null +++ b/packages/subgraph-service/test/disputes/draw.t.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "./DisputeManager.t.sol"; + +contract DisputeManagerDrawDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function testDraw_Dispute( + uint256 tokens, + uint256 tokensDispute + ) public useIndexer useProvision(tokens) { + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI32"), tokensDispute); + + resetPrank(users.arbitrator); + disputeManager.drawDispute(disputeID); + + assertEq(token.balanceOf(users.fisherman), fishermanPreviousBalance, "Fisherman should receive their deposit back."); + } + + function testDraw_QueryDisputeConflicting( + uint256 tokens + ) public useIndexer useProvision(tokens) { + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); + + resetPrank(users.arbitrator); + disputeManager.drawDispute(disputeID1); + + (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + assertTrue(status1 == IDisputeManager.DisputeStatus.Drawn, "Dispute 1 should be drawn."); + assertTrue(status2 == IDisputeManager.DisputeStatus.Drawn, "Dispute 2 should be drawn."); + } + + function testDraw_RevertIf_CallerIsNotArbitrator( + uint256 tokens, + uint256 tokensDispute + ) public useIndexer useProvision(tokens) { + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + bytes32 disputeID =_createIndexingDispute(allocationID,bytes32("POI1"), tokens); + + // attempt to draw dispute as fisherman + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.drawDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol index d5f1d48d0..6c365b89c 100644 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol @@ -83,7 +83,7 @@ contract MockHorizonStaking { // provisioned tokens that are not being used // `Provision.tokens - Provision.tokensThawing` - function getTokensAvailable(address serviceProvider, address verifier, uint32 delegationRatio) external view returns (uint256 tokens) { + function getTokensAvailable(address serviceProvider, address verifier, uint32) external view returns (uint256 tokens) { return _provisions[verifier][serviceProvider].tokens; } @@ -97,7 +97,7 @@ contract MockHorizonStaking { return true; } - function getDelegationPool(address serviceProvider, address verifier) external view returns (IHorizonStakingTypes.DelegationPool memory) { + function getDelegationPool(address, address) external pure returns (IHorizonStakingTypes.DelegationPool memory) { return IHorizonStakingTypes.DelegationPool({ tokens: 0, shares: 0, diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol new file mode 100644 index 000000000..b5af24f0b --- /dev/null +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +abstract contract Constants { + // Dispute Manager + uint64 internal constant disputePeriod = 300; // 5 minutes + uint256 internal constant minimumDeposit = 100 ether; // 100 GRT + uint32 internal constant fishermanRewardPercentage = 100000; // 10% + uint32 internal constant maxSlashingPercentage = 500000; // 50% + // Subgraph Service + uint256 internal constant minimumProvisionTokens = 1000 ether; + uint32 internal constant delegationRatio = 16; +} \ No newline at end of file diff --git a/packages/subgraph-service/test/utils/Users.sol b/packages/subgraph-service/test/utils/Users.sol new file mode 100644 index 000000000..91efa8f7a --- /dev/null +++ b/packages/subgraph-service/test/utils/Users.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +struct Users { + address governor; + address deployer; + address indexer; + address operator; + address gateway; + address verifier; + address delegator; + address arbitrator; + address fisherman; +} \ No newline at end of file diff --git a/packages/subgraph-service/test/utils/Utils.sol b/packages/subgraph-service/test/utils/Utils.sol new file mode 100644 index 000000000..47e4e68df --- /dev/null +++ b/packages/subgraph-service/test/utils/Utils.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +abstract contract Utils is Test { + /// @dev Stops the active prank and sets a new one. + function resetPrank(address msgSender) internal { + vm.stopPrank(); + vm.startPrank(msgSender); + } +} \ No newline at end of file From 29dedff11bf53824ca244f42ff7960d9fe6e4da4 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 19 Jun 2024 10:12:32 -0300 Subject: [PATCH 133/277] chore: add register tests --- ...hBaseTest.t.sol => SubgraphBaseTest.t.sol} | 11 ++-- .../test/disputes/DisputeManager.t.sol | 41 +------------ .../test/shared/SubgraphServiceShared.t.sol | 58 +++++++++++++++++++ .../subgraphService/SubgraphService.t.sol | 30 ++++++++++ .../test/subgraphService/register.t.sol | 53 +++++++++++++++++ .../subgraph-service/test/utils/Users.sol | 1 + 6 files changed, 150 insertions(+), 44 deletions(-) rename packages/subgraph-service/test/{GraphBaseTest.t.sol => SubgraphBaseTest.t.sol} (94%) create mode 100644 packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol create mode 100644 packages/subgraph-service/test/subgraphService/SubgraphService.t.sol create mode 100644 packages/subgraph-service/test/subgraphService/register.t.sol diff --git a/packages/subgraph-service/test/GraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol similarity index 94% rename from packages/subgraph-service/test/GraphBaseTest.t.sol rename to packages/subgraph-service/test/SubgraphBaseTest.t.sol index 4bf253e94..ba4d36287 100644 --- a/packages/subgraph-service/test/GraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -16,7 +16,7 @@ import { MockGRTToken } from "./mocks/MockGRTToken.sol"; import { MockHorizonStaking } from "./mocks/MockHorizonStaking.sol"; import { MockRewardsManager } from "./mocks/MockRewardsManager.sol"; -abstract contract GraphBaseTest is Utils, Constants { +abstract contract SubgraphBaseTest is Utils, Constants { /* * VARIABLES @@ -53,7 +53,8 @@ abstract contract GraphBaseTest is Utils, Constants { verifier: createUser("verifier"), delegator: createUser("delegator"), arbitrator: createUser("arbitrator"), - fisherman: createUser("fisherman") + fisherman: createUser("fisherman"), + rewardsDestination: createUser("rewardsDestination") }); deployProtocolContracts(); @@ -61,14 +62,14 @@ abstract contract GraphBaseTest is Utils, Constants { } function deployProtocolContracts() private { - changePrank(users.deployer); + resetPrank(users.deployer); staking = new MockHorizonStaking(address(token)); rewardsManager = new MockRewardsManager(); address tapVerifier = address(0xE3); address curation = address(0xE4); - changePrank(users.governor); + resetPrank(users.governor); controller = new Controller(); controller.setContractProxy(keccak256("GraphToken"), address(token)); controller.setContractProxy(keccak256("Staking"), address(staking)); @@ -80,7 +81,7 @@ abstract contract GraphBaseTest is Utils, Constants { controller.setContractProxy(keccak256("GraphProxyAdmin"), makeAddr("GraphProxyAdmin")); controller.setContractProxy(keccak256("Curation"), makeAddr("Curation")); - changePrank(users.deployer); + resetPrank(users.deployer); address disputeManagerImplementation = address(new DisputeManager(address(controller))); address disputeManagerProxy = UnsafeUpgrades.deployTransparentProxy( disputeManagerImplementation, diff --git a/packages/subgraph-service/test/disputes/DisputeManager.t.sol b/packages/subgraph-service/test/disputes/DisputeManager.t.sol index cf50ab122..8b6f95b12 100644 --- a/packages/subgraph-service/test/disputes/DisputeManager.t.sol +++ b/packages/subgraph-service/test/disputes/DisputeManager.t.sol @@ -9,58 +9,21 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; import { Attestation } from "../../contracts/libraries/Attestation.sol"; -import { GraphBaseTest } from "../GraphBaseTest.t.sol"; +import { SubgraphServiceSharedTest } from "../shared/SubgraphServiceShared.t.sol"; -contract DisputeManagerTest is GraphBaseTest { +contract DisputeManagerTest is SubgraphServiceSharedTest { using PPMMath for uint256; - /* - * VARIABLES - */ - - uint256 allocationIDPrivateKey; - address allocationID; - /* * MODIFIERS */ - modifier useIndexer { - vm.startPrank(users.indexer); - _; - vm.stopPrank(); - } - modifier useFisherman { vm.startPrank(users.fisherman); _; vm.stopPrank(); } - modifier useProvision(uint256 tokens) { - vm.assume(tokens > minimumProvisionTokens); - vm.assume(tokens < 10_000_000_000 ether); - staking.provision(tokens, address(subgraphService), maxSlashingPercentage, disputePeriod); - bytes32 subgraphDeployment = keccak256(abi.encodePacked("Subgraph Deployment ID")); - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - - subgraphService.register(users.indexer, abi.encode("url", "geoHash", address(0))); - - bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); - subgraphService.startService(users.indexer, data); - _; - } - - /* - * SET UP - */ - - function setUp() public override { - super.setUp(); - (allocationID, allocationIDPrivateKey) = makeAddrAndKey("allocationId"); - } - /* * HELPERS */ diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol new file mode 100644 index 000000000..228c7d5d3 --- /dev/null +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { SubgraphBaseTest } from "../SubgraphBaseTest.t.sol"; + +abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { + + /* + * VARIABLES + */ + + uint256 allocationIDPrivateKey; + address allocationID; + + /* + * MODIFIERS + */ + + modifier useIndexer { + vm.startPrank(users.indexer); + _; + vm.stopPrank(); + } + + modifier useProvision(uint256 tokens) { + vm.assume(tokens > minimumProvisionTokens); + vm.assume(tokens < 10_000_000_000 ether); + _createProvision(tokens); + bytes32 subgraphDeployment = keccak256(abi.encodePacked("Subgraph Deployment ID")); + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + + subgraphService.register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + subgraphService.startService(users.indexer, data); + _; + } + + /* + * SET UP + */ + + function setUp() public virtual override { + super.setUp(); + (allocationID, allocationIDPrivateKey) = makeAddrAndKey("allocationId"); + } + + /* + * HELPERS + */ + + function _createProvision(uint256 tokens) internal { + staking.provision(tokens, address(subgraphService), maxSlashingPercentage, disputePeriod); + } +} diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol new file mode 100644 index 000000000..f25cfe2b3 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { SubgraphServiceSharedTest } from "../shared/SubgraphServiceShared.t.sol"; + +contract SubgraphServiceTest is SubgraphServiceSharedTest { + + /* + * VARIABLES + */ + + /* + * MODIFIERS + */ + + /* + * SET UP + */ + + function setUp() public override { + super.setUp(); + } + + /* + * HELPERS + */ + +} diff --git a/packages/subgraph-service/test/subgraphService/register.t.sol b/packages/subgraph-service/test/subgraphService/register.t.sol new file mode 100644 index 000000000..5c7c5881e --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/register.t.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { ISubgraphService } from "../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "./SubgraphService.t.sol"; + +contract SubgraphServiceRegisterTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function testRegister_Indexer(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, 10_000_000_000 ether); + _createProvision(tokens); + bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); + vm.expectEmit(address(subgraphService)); + emit IDataService.ServiceProviderRegistered( + users.indexer, + data + ); + subgraphService.register(users.indexer, data); + + uint256 registeredAt; + string memory url; + string memory geoHash; + (registeredAt, url, geoHash) = subgraphService.indexers(users.indexer); + assertEq(registeredAt, block.timestamp); + assertEq(url, "url"); + assertEq(geoHash, "geoHash"); + } + + function testRegister_RevertIf_AlreadyRegistered( + uint256 tokens + ) public useIndexer useProvision(tokens) { + bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); + vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerAlreadyRegistered.selector)); + subgraphService.register(users.indexer, data); + } + + function testRegister_RevertWhen_InvalidProvision() public useIndexer { + bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerProvisionNotFound.selector, + users.indexer + )); + subgraphService.register(users.indexer, data); + } +} diff --git a/packages/subgraph-service/test/utils/Users.sol b/packages/subgraph-service/test/utils/Users.sol index 91efa8f7a..b2976f98a 100644 --- a/packages/subgraph-service/test/utils/Users.sol +++ b/packages/subgraph-service/test/utils/Users.sol @@ -11,4 +11,5 @@ struct Users { address delegator; address arbitrator; address fisherman; + address rewardsDestination; } \ No newline at end of file From f76fc3fc398d73feee652607485faee9b9030c78 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 19 Jun 2024 12:52:17 -0300 Subject: [PATCH 134/277] chore: use HorizonStaking instead of mock implementation --- .../test/SubgraphBaseTest.t.sol | 48 +++++++- .../test/mocks/MockHorizonStaking.sol | 111 ------------------ .../test/shared/SubgraphServiceShared.t.sol | 4 +- .../subgraph-service/test/utils/Constants.sol | 2 + 4 files changed, 48 insertions(+), 117 deletions(-) delete mode 100644 packages/subgraph-service/test/mocks/MockHorizonStaking.sol diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index ba4d36287..1da4c8a1f 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -4,6 +4,11 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; +import { GraphProxy } from "@graphprotocol/contracts/contracts/upgrades/GraphProxy.sol"; +import { GraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/GraphProxyAdmin.sol"; +import { HorizonStaking } from "@graphprotocol/horizon/contracts/staking/HorizonStaking.sol"; +import { HorizonStakingExtension } from "@graphprotocol/horizon/contracts/staking/HorizonStakingExtension.sol"; +import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; import { SubgraphService } from "../contracts/SubgraphService.sol"; @@ -13,7 +18,6 @@ import { Constants } from "./utils/Constants.sol"; import { Utils } from "./utils/Utils.sol"; import { MockGRTToken } from "./mocks/MockGRTToken.sol"; -import { MockHorizonStaking } from "./mocks/MockHorizonStaking.sol"; import { MockRewardsManager } from "./mocks/MockRewardsManager.sol"; abstract contract SubgraphBaseTest is Utils, Constants { @@ -24,12 +28,16 @@ abstract contract SubgraphBaseTest is Utils, Constants { /* Contracts */ + GraphProxyAdmin public proxyAdmin; Controller controller; SubgraphService subgraphService; DisputeManager disputeManager; + IHorizonStaking staking; + + HorizonStaking private stakingBase; + HorizonStakingExtension private stakingExtension; MockGRTToken token; - MockHorizonStaking staking; MockRewardsManager rewardsManager; /* Users */ @@ -58,21 +66,26 @@ abstract contract SubgraphBaseTest is Utils, Constants { }); deployProtocolContracts(); + setupProtocol(); + unpauseProtocol(); vm.stopPrank(); } function deployProtocolContracts() private { + resetPrank(users.governor); + proxyAdmin = new GraphProxyAdmin(); + controller = new Controller(); + resetPrank(users.deployer); - staking = new MockHorizonStaking(address(token)); + GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); rewardsManager = new MockRewardsManager(); address tapVerifier = address(0xE3); address curation = address(0xE4); resetPrank(users.governor); - controller = new Controller(); controller.setContractProxy(keccak256("GraphToken"), address(token)); - controller.setContractProxy(keccak256("Staking"), address(staking)); + controller.setContractProxy(keccak256("Staking"), address(stakingProxy)); controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); controller.setContractProxy(keccak256("GraphPayments"), makeAddr("GraphPayments")); controller.setContractProxy(keccak256("PaymentsEscrow"), makeAddr("PaymentsEscrow")); @@ -104,6 +117,31 @@ abstract contract SubgraphBaseTest is Utils, Constants { subgraphService = SubgraphService(subgraphServiceProxy); disputeManager.setSubgraphService(address(subgraphService)); + + stakingExtension = new HorizonStakingExtension( + address(controller), + address(subgraphService) + ); + stakingBase = new HorizonStaking( + address(controller), + address(stakingExtension), + address(subgraphService) + ); + + resetPrank(users.governor); + proxyAdmin.upgrade(stakingProxy, address(stakingBase)); + proxyAdmin.acceptProxy(stakingBase, stakingProxy); + staking = IHorizonStaking(address(stakingProxy)); + } + + function setupProtocol() private { + resetPrank(users.governor); + staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); + } + + function unpauseProtocol() private { + resetPrank(users.governor); + controller.setPaused(false); } function createUser(string memory name) private returns (address) { diff --git a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol b/packages/subgraph-service/test/mocks/MockHorizonStaking.sol deleted file mode 100644 index 6c365b89c..000000000 --- a/packages/subgraph-service/test/mocks/MockHorizonStaking.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; -import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol"; -import { MockGRTToken } from "./MockGRTToken.sol"; - -contract MockHorizonStaking { - mapping (address verifier => mapping (address serviceProvider => IHorizonStaking.Provision provision)) public _provisions; - MockGRTToken public grtToken; - - constructor(address _grtTokenAddress) { - grtToken = MockGRTToken(_grtTokenAddress); - } - - // whitelist/deny a verifier - function allowVerifier(address verifier, bool allow) external {} - - // deposit stake - function stake(uint256 tokens) external {} - - // create a provision - function provision(uint256 tokens, address verifier, uint32 maxVerifierCut, uint64 thawingPeriod) external { - IHorizonStaking.Provision memory newProvision = IHorizonStakingTypes.Provision({ - tokens: tokens, - tokensThawing: 0, - sharesThawing: 0, - maxVerifierCut: maxVerifierCut, - thawingPeriod: thawingPeriod, - createdAt: uint64(block.timestamp), - maxVerifierCutPending: maxVerifierCut, - thawingPeriodPending: thawingPeriod - }); - _provisions[verifier][msg.sender] = newProvision; - } - - function acceptProvision(address serviceProvider) external {} - - // initiate a thawing to remove tokens from a provision - function thaw(bytes32 provisionId, uint256 tokens) external returns (bytes32 thawRequestId) {} - - // moves thawed stake from a provision back into the provider's available stake - function deprovision(bytes32 thawRequestId) external {} - - // moves thawed stake from one provision into another provision - function reprovision(bytes32 thawRequestId, bytes32 provisionId) external {} - - // moves thawed stake back to the owner's account - stake is removed from the protocol - function withdraw(bytes32 thawRequestId) external {} - - // delegate tokens to a provider - function delegate(address serviceProvider, uint256 tokens) external {} - - // undelegate tokens - function undelegate( - address serviceProvider, - uint256 tokens, - bytes32[] calldata provisions - ) external returns (bytes32 thawRequestId) {} - - // slash a service provider - function slash(address serviceProvider, uint256 tokens, uint256 reward, address rewardsDestination) external { - grtToken.mint(rewardsDestination, reward); - grtToken.burnFrom(serviceProvider, tokens); - } - - // set the Service Provider's preferred provisions to be force thawed - function setForceThawProvisions(bytes32[] calldata provisions) external {} - - // total staked tokens to the provider - // `ServiceProvider.tokensStaked + DelegationPool.serviceProvider.tokens` - function getStake(address serviceProvider) external view returns (uint256 tokens) {} - - // staked tokens that are currently not provisioned, aka idle stake - // `getStake(serviceProvider) - ServiceProvider.tokensProvisioned` - function getIdleStake(address serviceProvider) external view returns (uint256 tokens) {} - - // staked tokens the provider can provision before hitting the delegation cap - // `ServiceProvider.tokensStaked * Staking.delegationRatio - Provision.tokensProvisioned` - function getCapacity(address serviceProvider) external view returns (uint256 tokens) {} - - // provisioned tokens that are not being used - // `Provision.tokens - Provision.tokensThawing` - function getTokensAvailable(address serviceProvider, address verifier, uint32) external view returns (uint256 tokens) { - return _provisions[verifier][serviceProvider].tokens; - } - - function getServiceProvider(address serviceProvider) external view returns (IHorizonStaking.ServiceProvider memory) {} - - function getProvision(address serviceProvider, address verifier) external view returns (IHorizonStaking.Provision memory) { - return _provisions[verifier][serviceProvider]; - } - - function isAuthorized(address, address, address) external pure returns (bool) { - return true; - } - - function getDelegationPool(address, address) external pure returns (IHorizonStakingTypes.DelegationPool memory) { - return IHorizonStakingTypes.DelegationPool({ - tokens: 0, - shares: 0, - tokensThawing: 0, - sharesThawing: 0 - }); - } - function getDelegationCut(address serviceProvider, uint8 paymentType) external view returns (uint256 delegationCut) {} - function addToDelegationPool(address serviceProvider, uint256 tokens) external {} - function stakeToProvision(address _serviceProvider, address _verifier, uint256 _tokens) external {} -} \ No newline at end of file diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index 228c7d5d3..07aed08f1 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -53,6 +53,8 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { */ function _createProvision(uint256 tokens) internal { - staking.provision(tokens, address(subgraphService), maxSlashingPercentage, disputePeriod); + token.approve(address(staking), tokens); + staking.stakeTo(users.indexer, tokens); + staking.provision(users.indexer, address(subgraphService), tokens, maxSlashingPercentage, disputePeriod); } } diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index b5af24f0b..b43a2adac 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -10,4 +10,6 @@ abstract contract Constants { // Subgraph Service uint256 internal constant minimumProvisionTokens = 1000 ether; uint32 internal constant delegationRatio = 16; + // Staking + uint64 internal constant MAX_THAWING_PERIOD = 28 days; } \ No newline at end of file From d44864112ea75db11cbc363f6c86e54d778a913a Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 20 Jun 2024 14:33:36 -0300 Subject: [PATCH 135/277] chore: add more subgraph service tests --- .../test/shared/SubgraphServiceShared.t.sol | 24 +++++--- .../subgraphService/SubgraphService.t.sol | 6 ++ .../test/subgraphService/allocate/start.t.sol | 61 +++++++++++++++++++ .../{ => provider}/register.t.sol | 36 ++++++++--- .../subgraphService/provision/accept.t.sol | 40 ++++++++++++ .../subgraph-service/test/utils/Constants.sol | 2 + 6 files changed, 154 insertions(+), 15 deletions(-) create mode 100644 packages/subgraph-service/test/subgraphService/allocate/start.t.sol rename packages/subgraph-service/test/subgraphService/{ => provider}/register.t.sol (58%) create mode 100644 packages/subgraph-service/test/subgraphService/provision/accept.t.sol diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index 07aed08f1..537df824e 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -13,6 +13,7 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { uint256 allocationIDPrivateKey; address allocationID; + bytes32 subgraphDeployment; /* * MODIFIERS @@ -28,14 +29,8 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { vm.assume(tokens > minimumProvisionTokens); vm.assume(tokens < 10_000_000_000 ether); _createProvision(tokens); - bytes32 subgraphDeployment = keccak256(abi.encodePacked("Subgraph Deployment ID")); - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - - subgraphService.register(users.indexer, abi.encode("url", "geoHash", address(0))); - - bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); - subgraphService.startService(users.indexer, data); + _registerIndexer(address(0)); + _startService(tokens); _; } @@ -46,6 +41,7 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { function setUp() public virtual override { super.setUp(); (allocationID, allocationIDPrivateKey) = makeAddrAndKey("allocationId"); + subgraphDeployment = keccak256(abi.encodePacked("Subgraph Deployment ID")); } /* @@ -57,4 +53,16 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { staking.stakeTo(users.indexer, tokens); staking.provision(users.indexer, address(subgraphService), tokens, maxSlashingPercentage, disputePeriod); } + + function _registerIndexer(address rewardsDestination) internal { + subgraphService.register(users.indexer, abi.encode("url", "geoHash", rewardsDestination)); + } + + function _startService(uint256 tokens) internal { + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + subgraphService.startService(users.indexer, data); + } } diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index f25cfe2b3..fb379737c 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -15,6 +15,12 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { * MODIFIERS */ + modifier useOperator { + vm.startPrank(users.operator); + _; + vm.stopPrank(); + } + /* * SET UP */ diff --git a/packages/subgraph-service/test/subgraphService/allocate/start.t.sol b/packages/subgraph-service/test/subgraphService/allocate/start.t.sol new file mode 100644 index 000000000..87d33ac22 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/allocate/start.t.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { Allocation } from "../../../contracts/libraries/Allocation.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function testStart_Allocation(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(tokens); + _registerIndexer(address(0)); + + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + vm.expectEmit(address(subgraphService)); + emit IDataService.ServiceStarted(users.indexer, data); + subgraphService.startService(users.indexer, data); + + Allocation.State memory allocation = subgraphService.getAllocation(allocationID); + assertEq(allocation.tokens, tokens); + assertEq(allocation.indexer, users.indexer); + assertEq(allocation.subgraphDeploymentId, subgraphDeployment); + assertEq(allocation.createdAt, block.timestamp); + assertEq(allocation.closedAt, 0); + assertEq(allocation.lastPOIPresentedAt, 0); + assertEq(allocation.accRewardsPerAllocatedToken, 0); + assertEq(allocation.accRewardsPending, 0); + } + + function testStart_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(tokens); + _registerIndexer(address(0)); + + resetPrank(users.operator); + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + )); + subgraphService.startService(users.indexer, data); + } +} diff --git a/packages/subgraph-service/test/subgraphService/register.t.sol b/packages/subgraph-service/test/subgraphService/provider/register.t.sol similarity index 58% rename from packages/subgraph-service/test/subgraphService/register.t.sol rename to packages/subgraph-service/test/subgraphService/provider/register.t.sol index 5c7c5881e..842c467bd 100644 --- a/packages/subgraph-service/test/subgraphService/register.t.sol +++ b/packages/subgraph-service/test/subgraphService/provider/register.t.sol @@ -5,8 +5,8 @@ import "forge-std/Test.sol"; import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; -import { ISubgraphService } from "../../contracts/interfaces/ISubgraphService.sol"; -import { SubgraphServiceTest } from "./SubgraphService.t.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; contract SubgraphServiceRegisterTest is SubgraphServiceTest { @@ -15,7 +15,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { */ function testRegister_Indexer(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, 10_000_000_000 ether); + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); _createProvision(tokens); bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); vm.expectEmit(address(subgraphService)); @@ -37,17 +37,39 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { function testRegister_RevertIf_AlreadyRegistered( uint256 tokens ) public useIndexer useProvision(tokens) { - bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerAlreadyRegistered.selector)); - subgraphService.register(users.indexer, data); + _registerIndexer(users.rewardsDestination); } function testRegister_RevertWhen_InvalidProvision() public useIndexer { - bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerProvisionNotFound.selector, users.indexer )); - subgraphService.register(users.indexer, data); + _registerIndexer(users.rewardsDestination); + } + + function testRegister_RevertWhen_NotAuthorized() public { + resetPrank(users.operator); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + )); + _registerIndexer(users.rewardsDestination); + } + + function testRegister_RevertWhen_InvalidProvisionValues(uint256 tokens) public useIndexer { + tokens = bound(tokens, 1, minimumProvisionTokens - 1); + _createProvision(tokens); + + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerInvalidValue.selector, + "tokens", + tokens, + minimumProvisionTokens, + maximumProvisionTokens + )); + _registerIndexer(address(0)); } } diff --git a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol new file mode 100644 index 000000000..dd6d73587 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function testAccept_Provision(uint256 tokens) public useIndexer useProvision(tokens) { + vm.expectEmit(address(subgraphService)); + emit IDataService.ProvisionAccepted(users.indexer); + subgraphService.acceptProvision(users.indexer, ""); + } + + function testAccept_RevertWhen_NotRegistered() public useIndexer { + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, + users.indexer + )); + subgraphService.acceptProvision(users.indexer, ""); + } + + function testAccept_RevertWhen_NotAuthorized() public { + resetPrank(users.operator); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + )); + subgraphService.acceptProvision(users.indexer, ""); + } +} diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index b43a2adac..26e73083b 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.26; abstract contract Constants { + uint256 internal constant MAX_TOKENS = 10_000_000_000 ether; // Dispute Manager uint64 internal constant disputePeriod = 300; // 5 minutes uint256 internal constant minimumDeposit = 100 ether; // 100 GRT @@ -9,6 +10,7 @@ abstract contract Constants { uint32 internal constant maxSlashingPercentage = 500000; // 50% // Subgraph Service uint256 internal constant minimumProvisionTokens = 1000 ether; + uint256 internal constant maximumProvisionTokens = type(uint256).max; uint32 internal constant delegationRatio = 16; // Staking uint64 internal constant MAX_THAWING_PERIOD = 28 days; From 826181c994f5e679ea22cc79aa6fb3eaf7b37cc1 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 20 Jun 2024 18:57:55 -0300 Subject: [PATCH 136/277] chore: start allocation tests --- .../test/subgraphService/allocate/start.t.sol | 78 +++++++++++++++++-- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/packages/subgraph-service/test/subgraphService/allocate/start.t.sol b/packages/subgraph-service/test/subgraphService/allocate/start.t.sol index 87d33ac22..0ecdb059c 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/start.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/start.t.sol @@ -7,10 +7,21 @@ import { IDataService } from "@graphprotocol/horizon/contracts/data-service/inte import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; import { Allocation } from "../../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { + /* + * Helpers + */ + + function _generateData(uint256 tokens) private view returns(bytes memory) { + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + return abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + } + /* * TESTS */ @@ -21,10 +32,7 @@ contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { _createProvision(tokens); _registerIndexer(address(0)); - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - - bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + bytes memory data = _generateData(tokens); vm.expectEmit(address(subgraphService)); emit IDataService.ServiceStarted(users.indexer, data); subgraphService.startService(users.indexer, data); @@ -47,10 +55,7 @@ contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { _registerIndexer(address(0)); resetPrank(users.operator); - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - - bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + bytes memory data = _generateData(tokens); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, users.operator, @@ -58,4 +63,61 @@ contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { )); subgraphService.startService(users.indexer, data); } + + function testStart_RevertWhen_NoValidProvision(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + bytes memory data = _generateData(tokens); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerProvisionNotFound.selector, + users.indexer + )); + subgraphService.startService(users.indexer, data); + } + + function testStart_RevertWhen_NotRegistered(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(tokens); + + bytes memory data = _generateData(tokens); + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, + users.indexer + )); + subgraphService.startService(users.indexer, data); + } + + function testStart_RevertWhen_ZeroAllocationId(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(tokens); + _registerIndexer(address(0)); + + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, address(0)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + bytes memory data = abi.encode(subgraphDeployment, tokens, address(0), abi.encodePacked(r, s, v)); + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerInvalidZeroAllocationId.selector + )); + subgraphService.startService(users.indexer, data); + } + + function testStart_RevertWhen_InvalidSignature(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(tokens); + _registerIndexer(address(0)); + + (address signer, uint256 signerPrivateKey) = makeAddrAndKey("invalidSigner"); + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, digest); + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerInvalidAllocationProof.selector, + signer, + allocationID + )); + subgraphService.startService(users.indexer, data); + } } From 215758a8c1b8fb42d153b992d8663129e86a09df Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 21 Jun 2024 12:33:56 -0300 Subject: [PATCH 137/277] chore: stop allocation tests started --- .../contracts/utilities/AllocationManager.sol | 6 +-- .../test/disputes/accept.t.sol | 10 ++--- .../test/disputes/cancel.t.sol | 6 +-- .../test/disputes/create.t.sol | 8 ++-- .../subgraph-service/test/disputes/draw.t.sol | 6 +-- .../test/shared/SubgraphServiceShared.t.sol | 2 +- .../test/subgraphService/allocate/start.t.sol | 45 ++++++++++++++++++- .../test/subgraphService/allocate/stop.t.sol | 33 ++++++++++++++ .../subgraphService/provider/register.t.sol | 2 +- .../subgraphService/provision/accept.t.sol | 2 +- 10 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 packages/subgraph-service/test/subgraphService/allocate/stop.t.sol diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 8d14da240..394ac3e57 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -384,15 +384,15 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca function _closeAllocation(address _allocationId) internal returns (Allocation.State memory) { Allocation.State memory allocation = allocations.get(_allocationId); - allocations.close(_allocationId); - allocationProvisionTracker.release(allocation.indexer, allocation.tokens); - // Take rewards snapshot to prevent other allos from counting tokens from this allo allocations.snapshotRewards( _allocationId, _graphRewardsManager().onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) ); + allocations.close(_allocationId); + allocationProvisionTracker.release(allocation.indexer, allocation.tokens); + // Update total allocated tokens for the subgraph deployment subgraphAllocatedTokens[allocation.subgraphDeploymentId] = subgraphAllocatedTokens[allocation.subgraphDeploymentId] - diff --git a/packages/subgraph-service/test/disputes/accept.t.sol b/packages/subgraph-service/test/disputes/accept.t.sol index 52b3f21ec..6292e65a4 100644 --- a/packages/subgraph-service/test/disputes/accept.t.sol +++ b/packages/subgraph-service/test/disputes/accept.t.sol @@ -18,7 +18,7 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 tokens, uint256 tokensDispute, uint256 tokensSlash - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); @@ -37,7 +37,7 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 tokens, uint256 tokensDispute, uint256 tokensSlash - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); @@ -55,7 +55,7 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_QueryDisputeConflicting( uint256 tokens, uint256 tokensSlash - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); @@ -93,7 +93,7 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 tokens, uint256 tokensDispute, uint256 tokensSlash - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); @@ -109,7 +109,7 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 tokens, uint256 tokensDispute, uint256 tokensSlash - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensSlash = bound(tokensSlash, uint256(maxSlashingPercentage).mulPPM(tokens) + 1, type(uint256).max); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI101"), tokensDispute); diff --git a/packages/subgraph-service/test/disputes/cancel.t.sol b/packages/subgraph-service/test/disputes/cancel.t.sol index db553a18b..741feda16 100644 --- a/packages/subgraph-service/test/disputes/cancel.t.sol +++ b/packages/subgraph-service/test/disputes/cancel.t.sol @@ -15,7 +15,7 @@ contract DisputeManagerCancelDisputeTest is DisputeManagerTest { function testCancel_Dispute( uint256 tokens, uint256 tokensDispute - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); @@ -31,7 +31,7 @@ contract DisputeManagerCancelDisputeTest is DisputeManagerTest { function testCancel_QueryDisputeConflicting( uint256 tokens - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); @@ -63,7 +63,7 @@ contract DisputeManagerCancelDisputeTest is DisputeManagerTest { function testCancel_RevertIf_CallerIsNotFisherman( uint256 tokens, uint256 tokensDispute - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensDispute = bound(tokensDispute, minimumDeposit, tokens); bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); diff --git a/packages/subgraph-service/test/disputes/create.t.sol b/packages/subgraph-service/test/disputes/create.t.sol index 058eee21c..5112aea0a 100644 --- a/packages/subgraph-service/test/disputes/create.t.sol +++ b/packages/subgraph-service/test/disputes/create.t.sol @@ -15,7 +15,7 @@ contract DisputeManagerCreateDisputeTest is DisputeManagerTest { function testCreate_IndexingDispute( uint256 tokens, uint256 tokensDispute - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensDispute = bound(tokensDispute, minimumDeposit, tokens); bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); @@ -24,7 +24,7 @@ contract DisputeManagerCreateDisputeTest is DisputeManagerTest { function testCreate_QueryDispute( uint256 tokens, uint256 tokensDispute - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensDispute = bound(tokensDispute, minimumDeposit, tokens); bytes32 disputeID = _createQueryDispute(tokensDispute); assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); @@ -32,7 +32,7 @@ contract DisputeManagerCreateDisputeTest is DisputeManagerTest { function testCreate_QueryDisputeConflict( uint256 tokens - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); @@ -56,7 +56,7 @@ contract DisputeManagerCreateDisputeTest is DisputeManagerTest { function testCreate_RevertWhen_DisputeAlreadyCreated( uint256 tokens, uint256 tokensDispute - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensDispute = bound(tokensDispute, minimumDeposit, tokens); bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); diff --git a/packages/subgraph-service/test/disputes/draw.t.sol b/packages/subgraph-service/test/disputes/draw.t.sol index 0139bf929..746d25ebd 100644 --- a/packages/subgraph-service/test/disputes/draw.t.sol +++ b/packages/subgraph-service/test/disputes/draw.t.sol @@ -16,7 +16,7 @@ contract DisputeManagerDrawDisputeTest is DisputeManagerTest { function testDraw_Dispute( uint256 tokens, uint256 tokensDispute - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI32"), tokensDispute); @@ -29,7 +29,7 @@ contract DisputeManagerDrawDisputeTest is DisputeManagerTest { function testDraw_QueryDisputeConflicting( uint256 tokens - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); @@ -59,7 +59,7 @@ contract DisputeManagerDrawDisputeTest is DisputeManagerTest { function testDraw_RevertIf_CallerIsNotArbitrator( uint256 tokens, uint256 tokensDispute - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { tokensDispute = bound(tokensDispute, minimumDeposit, tokens); bytes32 disputeID =_createIndexingDispute(allocationID,bytes32("POI1"), tokens); diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index 537df824e..3db0509ec 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -25,7 +25,7 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { vm.stopPrank(); } - modifier useProvision(uint256 tokens) { + modifier useAllocation(uint256 tokens) { vm.assume(tokens > minimumProvisionTokens); vm.assume(tokens < 10_000_000_000 ether); _createProvision(tokens); diff --git a/packages/subgraph-service/test/subgraphService/allocate/start.t.sol b/packages/subgraph-service/test/subgraphService/allocate/start.t.sol index 0ecdb059c..65e4ec35b 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/start.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/start.t.sol @@ -5,9 +5,12 @@ import "forge-std/Test.sol"; import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; -import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; + import { Allocation } from "../../../contracts/libraries/Allocation.sol"; import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { @@ -46,6 +49,9 @@ contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { assertEq(allocation.lastPOIPresentedAt, 0); assertEq(allocation.accRewardsPerAllocatedToken, 0); assertEq(allocation.accRewardsPending, 0); + + uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); + assertEq(subgraphAllocatedTokens, tokens); } function testStart_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer { @@ -120,4 +126,41 @@ contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { )); subgraphService.startService(users.indexer, data); } + + function testStart_RevertWhen_ArealdyExists(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(tokens); + _registerIndexer(address(0)); + + bytes32 slot = keccak256(abi.encode(allocationID, uint256(158))); + vm.store(address(subgraphService), slot, bytes32(uint256(uint160(users.indexer)))); + vm.store(address(subgraphService), bytes32(uint256(slot) + 1), subgraphDeployment); + + bytes memory data = _generateData(tokens); + vm.expectRevert(abi.encodeWithSelector( + LegacyAllocation.LegacyAllocationExists.selector, + allocationID + )); + subgraphService.startService(users.indexer, data); + } + + function testStart_RevertWhen_NotEnoughTokens( + uint256 tokens, + uint256 lockTokens + ) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS - 1); + lockTokens = bound(lockTokens, tokens + 1, MAX_TOKENS); + + _createProvision(tokens); + _registerIndexer(address(0)); + + bytes memory data = _generateData(lockTokens); + vm.expectRevert(abi.encodeWithSelector( + ProvisionTracker.ProvisionTrackerInsufficientTokens.selector, + tokens, + lockTokens + )); + subgraphService.startService(users.indexer, data); + } } diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol new file mode 100644 index 000000000..c1b5170d8 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; + +import { Allocation } from "../../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { + + /* + * Helpers + */ + + /* + * TESTS + */ + + function testStop_Allocation(uint256 tokens) public useIndexer useAllocation(tokens) { + assertTrue(subgraphService.isActiveAllocation(allocationID)); + bytes memory data = abi.encode(allocationID); + // vm.expectEmit(address(subgraphService)); + // emit IDataService.ServiceStopped(users.indexer, data); + subgraphService.stopService(users.indexer, data); + } +} diff --git a/packages/subgraph-service/test/subgraphService/provider/register.t.sol b/packages/subgraph-service/test/subgraphService/provider/register.t.sol index 842c467bd..2605d9e00 100644 --- a/packages/subgraph-service/test/subgraphService/provider/register.t.sol +++ b/packages/subgraph-service/test/subgraphService/provider/register.t.sol @@ -36,7 +36,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { function testRegister_RevertIf_AlreadyRegistered( uint256 tokens - ) public useIndexer useProvision(tokens) { + ) public useIndexer useAllocation(tokens) { vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerAlreadyRegistered.selector)); _registerIndexer(users.rewardsDestination); } diff --git a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol index dd6d73587..8e98078c6 100644 --- a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol +++ b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol @@ -14,7 +14,7 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { * TESTS */ - function testAccept_Provision(uint256 tokens) public useIndexer useProvision(tokens) { + function testAccept_Provision(uint256 tokens) public useIndexer useAllocation(tokens) { vm.expectEmit(address(subgraphService)); emit IDataService.ProvisionAccepted(users.indexer); subgraphService.acceptProvision(users.indexer, ""); From cd7723937b2bfaee197b95d3804719ae22ba8d5a Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 25 Jun 2024 17:13:41 -0300 Subject: [PATCH 138/277] chore: stop allocation tests --- .../test/subgraphService/allocate/stop.t.sol | 38 ++++++++++++++++++- .../subgraphService/collect/collect.t.sol | 33 ++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 packages/subgraph-service/test/subgraphService/collect/collect.t.sol diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index c1b5170d8..06a2019ec 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -26,8 +26,42 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { function testStop_Allocation(uint256 tokens) public useIndexer useAllocation(tokens) { assertTrue(subgraphService.isActiveAllocation(allocationID)); bytes memory data = abi.encode(allocationID); - // vm.expectEmit(address(subgraphService)); - // emit IDataService.ServiceStopped(users.indexer, data); + vm.expectEmit(address(subgraphService)); + emit IDataService.ServiceStopped(users.indexer, data); + subgraphService.stopService(users.indexer, data); + + uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); + assertEq(subgraphAllocatedTokens, 0); + } + + function testStop_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { + resetPrank(users.operator); + bytes memory data = abi.encode(allocationID); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + )); + subgraphService.stopService(users.indexer, data); + } + + function testStop_RevertWhen_NotRegistered() public useIndexer { + bytes memory data = abi.encode(allocationID); + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, + users.indexer + )); + subgraphService.stopService(users.indexer, data); + } + + function testStop_RevertWhen_NotOpen(uint256 tokens) public useIndexer useAllocation(tokens) { + bytes memory data = abi.encode(allocationID); + subgraphService.stopService(users.indexer, data); + vm.expectRevert(abi.encodeWithSelector( + Allocation.AllocationClosed.selector, + allocationID, + block.timestamp + )); subgraphService.stopService(users.indexer, data); } } diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol new file mode 100644 index 000000000..b9fc3d77d --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; + +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceRegisterTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function testCollect_Tokens(uint256 tokens) public useIndexer useAllocation(tokens) { + + } + + function testCollect_RevertWhen_InvalidPayment( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes invalidPaymentType = IGraphPayments.PaymentTypes.IndexingFee; + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceInvalidPaymentType.selector, + invalidPaymentType + )); + subgraphService.collect(users.indexer, invalidPaymentType, ""); + } +} From 6b99a6d69a61d6f0da18c2daab0d01ff2b6e2dde Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 26 Jun 2024 14:17:02 -0300 Subject: [PATCH 139/277] WIP --- .../test/SubgraphBaseTest.t.sol | 62 ++++++++++++++++--- .../subgraphService/SubgraphService.t.sol | 2 +- .../subgraphService/collect/collect.t.sol | 36 ++++++++++- .../subgraph-service/test/utils/Constants.sol | 5 ++ 4 files changed, 94 insertions(+), 11 deletions(-) diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 1da4c8a1f..b48a18d33 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -4,17 +4,23 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; +import { GraphPayments } from "@graphprotocol/horizon/contracts/payments/GraphPayments.sol"; import { GraphProxy } from "@graphprotocol/contracts/contracts/upgrades/GraphProxy.sol"; import { GraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/GraphProxyAdmin.sol"; import { HorizonStaking } from "@graphprotocol/horizon/contracts/staking/HorizonStaking.sol"; import { HorizonStakingExtension } from "@graphprotocol/horizon/contracts/staking/HorizonStakingExtension.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; +import { IPaymentsEscrow } from "@graphprotocol/horizon/contracts/interfaces/IPaymentsEscrow.sol"; +import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; +import { TAPCollector } from "@graphprotocol/horizon/contracts/payments/collectors/TAPCollector.sol"; +import { PaymentsEscrow } from "@graphprotocol/horizon/contracts/payments/PaymentsEscrow.sol"; import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; -import { SubgraphService } from "../contracts/SubgraphService.sol"; +import { Constants } from "./utils/Constants.sol"; import { DisputeManager } from "../contracts/DisputeManager.sol"; +import { SubgraphService } from "../contracts/SubgraphService.sol"; import { Users } from "./utils/Users.sol"; -import { Constants } from "./utils/Constants.sol"; import { Utils } from "./utils/Utils.sol"; import { MockGRTToken } from "./mocks/MockGRTToken.sol"; @@ -28,11 +34,14 @@ abstract contract SubgraphBaseTest is Utils, Constants { /* Contracts */ - GraphProxyAdmin public proxyAdmin; + GraphProxyAdmin proxyAdmin; Controller controller; SubgraphService subgraphService; DisputeManager disputeManager; IHorizonStaking staking; + IGraphPayments graphPayments; + IPaymentsEscrow escrow; + ITAPCollector tapCollector; HorizonStaking private stakingBase; HorizonStakingExtension private stakingExtension; @@ -80,15 +89,40 @@ abstract contract SubgraphBaseTest is Utils, Constants { GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); rewardsManager = new MockRewardsManager(); - address tapVerifier = address(0xE3); - address curation = address(0xE4); + // GraphPayments predict address + bytes32 saltGraphPayments = keccak256("GraphPaymentsSalt"); + bytes32 paymentsHash = keccak256(bytes.concat( + vm.getCode("GraphPayments.sol:GraphPayments"), + abi.encode(address(controller), protocolPaymentCut) + )); + address predictedGraphPaymentsAddress = vm.computeCreate2Address( + saltGraphPayments, + paymentsHash, + users.deployer + ); + + // GraphEscrow predict address + bytes32 saltEscrow = keccak256("GraphEscrowSalt"); + bytes32 escrowHash = keccak256(bytes.concat( + vm.getCode("PaymentsEscrow.sol:PaymentsEscrow"), + abi.encode( + address(controller), + revokeCollectorThawingPeriod, + withdrawEscrowThawingPeriod + ) + )); + address predictedEscrowAddress = vm.computeCreate2Address( + saltEscrow, + escrowHash, + users.deployer + ); resetPrank(users.governor); controller.setContractProxy(keccak256("GraphToken"), address(token)); controller.setContractProxy(keccak256("Staking"), address(stakingProxy)); controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); - controller.setContractProxy(keccak256("GraphPayments"), makeAddr("GraphPayments")); - controller.setContractProxy(keccak256("PaymentsEscrow"), makeAddr("PaymentsEscrow")); + controller.setContractProxy(keccak256("GraphPayments"), predictedGraphPaymentsAddress); + controller.setContractProxy(keccak256("PaymentsEscrow"), predictedEscrowAddress); controller.setContractProxy(keccak256("EpochManager"), makeAddr("EpochManager")); controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); controller.setContractProxy(keccak256("GraphProxyAdmin"), makeAddr("GraphProxyAdmin")); @@ -106,8 +140,10 @@ abstract contract SubgraphBaseTest is Utils, Constants { ); disputeManager = DisputeManager(disputeManagerProxy); + tapCollector = new TAPCollector("TAPCollector", "1", address(controller)); + address curation = address(0xE4); address subgraphServiceImplementation = address( - new SubgraphService(address(controller), address(disputeManager), tapVerifier, curation) + new SubgraphService(address(controller), address(disputeManager), address(tapCollector), curation) ); address subgraphServiceProxy = UnsafeUpgrades.deployTransparentProxy( subgraphServiceImplementation, @@ -128,6 +164,16 @@ abstract contract SubgraphBaseTest is Utils, Constants { address(subgraphService) ); + graphPayments = new GraphPayments{salt: saltGraphPayments}( + address(controller), + protocolPaymentCut + ); + escrow = new PaymentsEscrow{salt: saltEscrow}( + address(controller), + revokeCollectorThawingPeriod, + withdrawEscrowThawingPeriod + ); + resetPrank(users.governor); proxyAdmin.upgrade(stakingProxy, address(stakingBase)); proxyAdmin.acceptProxy(stakingBase, stakingProxy); diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index fb379737c..65498e485 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -25,7 +25,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { * SET UP */ - function setUp() public override { + function setUp() public virtual override { super.setUp(); } diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index b9fc3d77d..7b11b0f35 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -5,6 +5,7 @@ import "forge-std/Test.sol"; import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; @@ -12,12 +13,43 @@ import { SubgraphServiceTest } from "../SubgraphService.t.sol"; contract SubgraphServiceRegisterTest is SubgraphServiceTest { + address signer; + uint256 signerPrivateKey; + + /* + * HELPERS + */ + + function _getRAV() private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { + return ITAPCollector.ReceiptAggregateVoucher({ + dataService: address(subgraphService), + serviceProvider: users.indexer, + timestampNs: 0, + valueAggregate: 0, + metadata: abi.encode(allocationID) + }); + } + + /* + * SET UP + */ + + function setUp() public virtual override { + super.setUp(); + (signer, signerPrivateKey) = makeAddrAndKey("signer"); + } + /* * TESTS */ - function testCollect_Tokens(uint256 tokens) public useIndexer useAllocation(tokens) { - + function testCollect_QueryFees(uint256 tokens) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes invalidPaymentType = IGraphPayments.PaymentTypes.QueryFee; + ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(); + bytes32 messageHash = tapCollector.encodeRAV(rav); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, messageHash); + bytes memory data = abi.encode(rav, r, s, v); + subgraphService.collect(users.indexer, invalidPaymentType, data); } function testCollect_RevertWhen_InvalidPayment( diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index 26e73083b..207680655 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -14,4 +14,9 @@ abstract contract Constants { uint32 internal constant delegationRatio = 16; // Staking uint64 internal constant MAX_THAWING_PERIOD = 28 days; + // GraphEscrow parameters + uint256 internal constant withdrawEscrowThawingPeriod = 60; + uint256 internal constant revokeCollectorThawingPeriod = 60; + // GraphPayments parameters + uint256 internal constant protocolPaymentCut = 10000; } \ No newline at end of file From 30973f120e3055081f3d1ca533235bc4c01845df Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 27 Jun 2024 18:01:02 -0300 Subject: [PATCH 140/277] chore: subgraph service unit tests --- .../contracts/SubgraphService.sol | 25 +++++++ .../contracts/SubgraphServiceStorage.sol | 2 +- .../contracts/interfaces/ISubgraphService.sol | 36 ++++++++++ .../contracts/utilities/AllocationManager.sol | 16 +++++ packages/subgraph-service/foundry.toml | 1 + .../test/SubgraphBaseTest.t.sol | 14 ++-- .../test/mocks/MockCuration.sol | 11 +++ .../test/mocks/MockRewardsManager.sol | 39 +++++++++- .../subgraphService/collect/collect.t.sol | 71 ++++++++++++++++--- .../subgraph-service/test/utils/Constants.sol | 6 ++ 10 files changed, 206 insertions(+), 15 deletions(-) create mode 100644 packages/subgraph-service/test/mocks/MockCuration.sol diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index bd36002a0..403d99dcf 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -19,6 +19,8 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; +import "forge-std/console.sol"; + contract SubgraphService is Initializable, OwnableUpgradeable, @@ -340,6 +342,29 @@ contract SubgraphService is _setDelegationRatio(delegationRatio); } + /** + * @notice See {ISubgraphService.setStakeToFeesRatio} + */ + function setStakeToFeesRatio(uint32 _stakeToFeesRatio) external override onlyOwner { + stakeToFeesRatio = _stakeToFeesRatio; + emit StakeToFeesRatioSet(_stakeToFeesRatio); + } + + /** + * @notice See {ISubgraphService.setMaxPOIStaleness} + */ + function setMaxPOIStaleness(uint256 maxPOIStaleness) external override onlyOwner { + _setMaxPOIStaleness(maxPOIStaleness); + } + + /** + * @notice See {ISubgraphService.setPaymentCuts} + */ + function setPaymentCuts(IGraphPayments.PaymentTypes paymentType, uint128 serviceCut, uint128 curationCut) external override onlyOwner { + paymentCuts[paymentType] = PaymentCuts(serviceCut, curationCut); + emit PaymentCutsSet(paymentType, serviceCut, curationCut); + } + /** * @notice See {ISubgraphService.getAllocation} */ diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 50e72b417..e0f23aa88 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -9,7 +9,7 @@ abstract contract SubgraphServiceV1Storage { mapping(address indexer => ISubgraphService.Indexer details) public indexers; ///@notice Multiplier for how many tokens back collected query fees - uint256 public stakeToFeesRatio; + uint32 public stakeToFeesRatio; /// @notice The fees cut taken by the subgraph service mapping(IGraphPayments.PaymentTypes paymentType => ISubgraphService.PaymentCuts paymentCuts) public paymentCuts; diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 39fc7430d..096d101a5 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -48,6 +48,20 @@ interface ISubgraphService is IDataServiceFees { uint256 tokensSubgraphService ); + /** + * @notice Emitted when the stake to fees ratio is set. + * @param ratio The stake to fees ratio + */ + event StakeToFeesRatioSet(uint32 ratio); + + /** + * @notice Emmited when payment cuts are set for a payment type + * @param paymentType The payment type + * @param serviceCut The service cut for the payment type + * @param curationCut The curation cut for the payment type + */ + event PaymentCutsSet(IGraphPayments.PaymentTypes paymentType, uint128 serviceCut, uint128 curationCut); + /** * @notice Thrown when an indexer tries to register with an empty URL */ @@ -133,6 +147,28 @@ interface ISubgraphService is IDataServiceFees { */ function setDelegationRatio(uint32 delegationRatio) external; + /** + * @notice Sets the stake to fees ratio + * @param stakeToFeesRatio The stake to fees ratio + */ + function setStakeToFeesRatio(uint32 stakeToFeesRatio) external; + + /** + * @notice Sets the max POI staleness + * See {AllocationManagerV1Storage-maxPOIStaleness} for more details. + * @param maxPOIStaleness The max POI staleness in seconds + */ + function setMaxPOIStaleness(uint256 maxPOIStaleness) external; + + /** + * @notice Sets the payment cuts for a payment type + * @dev Emits a {PaymentCutsSet} event + * @param paymentType The payment type + * @param serviceCut The service cut for the payment type + * @param curationCut The curation cut for the payment type + */ + function setPaymentCuts(IGraphPayments.PaymentTypes paymentType, uint128 serviceCut, uint128 curationCut) external; + /** * @notice Sets the rewards destination for an indexer to receive indexing rewards * @dev Emits a {RewardsDestinationSet} event diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 394ac3e57..850b3fd13 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -114,6 +114,12 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca */ event RewardsDestinationSet(address indexed indexer, address indexed rewardsDestination); + /** + * @notice Emitted when the maximum POI staleness is updated + * @param maxPOIStaleness The max POI staleness in seconds + */ + event MaxPOIStalenessSet(uint256 maxPOIStaleness); + /** * @notice Thrown when an allocation proof is invalid * Both `signer` and `allocationId` should match for a valid proof. @@ -412,6 +418,16 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca emit RewardsDestinationSet(_indexer, _rewardsDestination); } + /** + * @notice Sets the maximum amount of time, in seconds, allowed between presenting POIs to qualify for indexing rewards + * @dev Emits a {MaxPOIStalenessSet} event + * @param _maxPOIStaleness The max POI staleness in seconds + */ + function _setMaxPOIStaleness(uint256 _maxPOIStaleness) internal { + maxPOIStaleness = _maxPOIStaleness; + emit MaxPOIStalenessSet(_maxPOIStaleness); + } + /** * @notice Gets the details of an allocation * @param _allocationId The id of the allocation diff --git a/packages/subgraph-service/foundry.toml b/packages/subgraph-service/foundry.toml index d4c30311f..235a58eb9 100644 --- a/packages/subgraph-service/foundry.toml +++ b/packages/subgraph-service/foundry.toml @@ -7,6 +7,7 @@ cache_path = 'cache_forge' optimizer = true optimizer-runs = 200 via_ir = true +fs_permissions = [{ access = "read", path = "./"}] [profile.lite] optimizer = false diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index b48a18d33..8344875bf 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -23,6 +23,7 @@ import { SubgraphService } from "../contracts/SubgraphService.sol"; import { Users } from "./utils/Users.sol"; import { Utils } from "./utils/Utils.sol"; +import { MockCuration } from "./mocks/MockCuration.sol"; import { MockGRTToken } from "./mocks/MockGRTToken.sol"; import { MockRewardsManager } from "./mocks/MockRewardsManager.sol"; @@ -46,6 +47,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { HorizonStaking private stakingBase; HorizonStakingExtension private stakingExtension; + MockCuration curation; MockGRTToken token; MockRewardsManager rewardsManager; @@ -87,7 +89,8 @@ abstract contract SubgraphBaseTest is Utils, Constants { resetPrank(users.deployer); GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); - rewardsManager = new MockRewardsManager(); + rewardsManager = new MockRewardsManager(token, rewardsPerSignal); + curation = new MockCuration(); // GraphPayments predict address bytes32 saltGraphPayments = keccak256("GraphPaymentsSalt"); @@ -126,7 +129,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { controller.setContractProxy(keccak256("EpochManager"), makeAddr("EpochManager")); controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); controller.setContractProxy(keccak256("GraphProxyAdmin"), makeAddr("GraphProxyAdmin")); - controller.setContractProxy(keccak256("Curation"), makeAddr("Curation")); + controller.setContractProxy(keccak256("Curation"), address(curation)); resetPrank(users.deployer); address disputeManagerImplementation = address(new DisputeManager(address(controller))); @@ -141,9 +144,8 @@ abstract contract SubgraphBaseTest is Utils, Constants { disputeManager = DisputeManager(disputeManagerProxy); tapCollector = new TAPCollector("TAPCollector", "1", address(controller)); - address curation = address(0xE4); address subgraphServiceImplementation = address( - new SubgraphService(address(controller), address(disputeManager), address(tapCollector), curation) + new SubgraphService(address(controller), address(disputeManager), address(tapCollector), address(curation)) ); address subgraphServiceProxy = UnsafeUpgrades.deployTransparentProxy( subgraphServiceImplementation, @@ -183,6 +185,10 @@ abstract contract SubgraphBaseTest is Utils, Constants { function setupProtocol() private { resetPrank(users.governor); staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); + resetPrank(users.deployer); + subgraphService.setStakeToFeesRatio(stakeToFeesRatio); + subgraphService.setMaxPOIStaleness(maxPOIStaleness); + subgraphService.setPaymentCuts(IGraphPayments.PaymentTypes.QueryFee, serviceCut, curationCut); } function unpauseProtocol() private { diff --git a/packages/subgraph-service/test/mocks/MockCuration.sol b/packages/subgraph-service/test/mocks/MockCuration.sol new file mode 100644 index 000000000..68b4a8ce9 --- /dev/null +++ b/packages/subgraph-service/test/mocks/MockCuration.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.26; + +contract MockCuration { + function isCurated(bytes32) public pure returns (bool) { + return true; + } + + function collect(bytes32, uint256) external {} +} \ No newline at end of file diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index 158feef50..dad236c7a 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -4,8 +4,32 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import { IRewardsManager } from "@graphprotocol/contracts/contracts/rewards/IRewardsManager.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; + +import { MockGRTToken } from "./MockGRTToken.sol"; + +interface IRewardsIssuer { + function getAllocationData( + address allocationId + ) + external + view + returns (address indexer, bytes32 subgraphDeploymentId, uint256 tokens, uint256 accRewardsPerAllocatedToken); +} contract MockRewardsManager is IRewardsManager { + using PPMMath for uint256; + + MockGRTToken public token; + uint256 public rewardsPerSignal; + + uint256 private constant FIXED_POINT_SCALING_FACTOR = 1e18; + + constructor(MockGRTToken _token, uint256 _rewardsPerSignal) { + token = _token; + rewardsPerSignal = _rewardsPerSignal; + } + // -- Config -- function setIssuancePerBlock(uint256) external {} @@ -40,7 +64,20 @@ contract MockRewardsManager is IRewardsManager { function updateAccRewardsPerSignal() external returns (uint256) {} - function takeRewards(address) external returns (uint256) {} + function takeRewards(address _allocationID) external returns (uint256) { + address rewardsIssuer = msg.sender; + ( + , + , + uint256 tokens, + uint256 accRewardsPerAllocatedToken + ) = IRewardsIssuer(rewardsIssuer).getAllocationData(_allocationID); + + uint256 accRewardsPerTokens = tokens.mulPPM(rewardsPerSignal); + uint256 rewards = accRewardsPerTokens - accRewardsPerAllocatedToken; + token.mint(rewardsIssuer, rewards); + return rewards; + } // -- Hooks -- diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index 7b11b0f35..0683c4712 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -6,12 +6,15 @@ import "forge-std/Test.sol"; import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; contract SubgraphServiceRegisterTest is SubgraphServiceTest { + using PPMMath for uint128; + using PPMMath for uint256; address signer; uint256 signerPrivateKey; @@ -20,16 +23,38 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { * HELPERS */ - function _getRAV() private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { + function _getQueryFeeEncodedData( + uint128 tokens + ) private view returns (bytes memory) { + ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(tokens); + bytes32 messageHash = tapCollector.encodeRAV(rav); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, messageHash); + bytes memory signature = abi.encodePacked(r, s, v); + ITAPCollector.SignedRAV memory signedRAV = ITAPCollector.SignedRAV(rav, signature); + return abi.encode(signedRAV); + } + + function _getRAV(uint128 tokens) private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { return ITAPCollector.ReceiptAggregateVoucher({ dataService: address(subgraphService), serviceProvider: users.indexer, timestampNs: 0, - valueAggregate: 0, + valueAggregate: tokens, metadata: abi.encode(allocationID) }); } + function _approveCollector(uint128 tokens) private { + address msgSender; + (, msgSender,) = vm.readCallers(); + resetPrank(signer); + mint(signer, tokens); + escrow.approveCollector(address(tapCollector), tokens); + token.approve(address(escrow), tokens); + escrow.deposit(users.indexer, tokens); + resetPrank(msgSender); + } + /* * SET UP */ @@ -37,19 +62,47 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { function setUp() public virtual override { super.setUp(); (signer, signerPrivateKey) = makeAddrAndKey("signer"); + vm.label({ account: signer, newLabel: "signer" }); } /* * TESTS */ - function testCollect_QueryFees(uint256 tokens) public useIndexer useAllocation(tokens) { - IGraphPayments.PaymentTypes invalidPaymentType = IGraphPayments.PaymentTypes.QueryFee; - ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(); - bytes32 messageHash = tapCollector.encodeRAV(rav); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, messageHash); - bytes memory data = abi.encode(rav, r, s, v); - subgraphService.collect(users.indexer, invalidPaymentType, data); + function testCollect_QueryFees( + uint256 tokens, + uint256 tokensPayment + ) public useIndexer useAllocation(tokens) { + vm.assume(tokens > minimumProvisionTokens * stakeToFeesRatio); + uint256 maxTokensPayment = tokens / stakeToFeesRatio > type(uint128).max ? type(uint128).max : tokens / stakeToFeesRatio; + tokensPayment = bound(tokensPayment, minimumProvisionTokens, maxTokensPayment); + uint128 tokensPayment128 = uint128(tokensPayment); + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; + bytes memory data = _getQueryFeeEncodedData(tokensPayment128); + + uint256 indexerPreviousBalance = token.balanceOf(users.indexer); + + _approveCollector(tokensPayment128); + subgraphService.collect(users.indexer, paymentType, data); + + uint256 indexerBalance = token.balanceOf(users.indexer); + uint256 tokensProtocol = tokensPayment128.mulPPM(protocolPaymentCut); + uint256 curationTokens = tokensPayment128.mulPPMRoundUp(curationCut); + uint256 dataServiceTokens = tokensPayment128.mulPPM(serviceCut + curationCut) - curationTokens; + + uint256 expectedIndexerTokensPayment = tokensPayment128 - tokensProtocol - dataServiceTokens - curationTokens; + assertEq(indexerBalance, indexerPreviousBalance + expectedIndexerTokensPayment); + } + + function testCollect_IndexingFees(uint256 tokens) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory data = abi.encode(allocationID, bytes32("POI1")); + + uint256 indexerPreviousProvisionBalance = staking.getProviderTokensAvailable(users.indexer, address(subgraphService)); + subgraphService.collect(users.indexer, paymentType, data); + + uint256 indexerProvisionBalance = staking.getProviderTokensAvailable(users.indexer, address(subgraphService)); + assertEq(indexerProvisionBalance, indexerPreviousProvisionBalance + tokens.mulPPM(rewardsPerSignal)); } function testCollect_RevertWhen_InvalidPayment( diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index 207680655..1d07ec817 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -12,6 +12,10 @@ abstract contract Constants { uint256 internal constant minimumProvisionTokens = 1000 ether; uint256 internal constant maximumProvisionTokens = type(uint256).max; uint32 internal constant delegationRatio = 16; + uint32 public constant stakeToFeesRatio = 2; + uint256 public constant maxPOIStaleness = 28 days; + uint128 public constant serviceCut = 10000; + uint128 public constant curationCut = 10000; // Staking uint64 internal constant MAX_THAWING_PERIOD = 28 days; // GraphEscrow parameters @@ -19,4 +23,6 @@ abstract contract Constants { uint256 internal constant revokeCollectorThawingPeriod = 60; // GraphPayments parameters uint256 internal constant protocolPaymentCut = 10000; + // RewardsMananger parameters + uint256 public constant rewardsPerSignal = 10000; } \ No newline at end of file From 19cb2877535bd5679afffa9ca2ab5251eecdf927 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 27 Jun 2024 18:13:04 -0300 Subject: [PATCH 141/277] fix: revert unit type change --- packages/subgraph-service/contracts/SubgraphService.sol | 4 +--- .../subgraph-service/contracts/SubgraphServiceStorage.sol | 2 +- .../contracts/interfaces/ISubgraphService.sol | 4 ++-- packages/subgraph-service/test/utils/Constants.sol | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 403d99dcf..0045b970d 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -19,8 +19,6 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; -import "forge-std/console.sol"; - contract SubgraphService is Initializable, OwnableUpgradeable, @@ -345,7 +343,7 @@ contract SubgraphService is /** * @notice See {ISubgraphService.setStakeToFeesRatio} */ - function setStakeToFeesRatio(uint32 _stakeToFeesRatio) external override onlyOwner { + function setStakeToFeesRatio(uint256 _stakeToFeesRatio) external override onlyOwner { stakeToFeesRatio = _stakeToFeesRatio; emit StakeToFeesRatioSet(_stakeToFeesRatio); } diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index e0f23aa88..50e72b417 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -9,7 +9,7 @@ abstract contract SubgraphServiceV1Storage { mapping(address indexer => ISubgraphService.Indexer details) public indexers; ///@notice Multiplier for how many tokens back collected query fees - uint32 public stakeToFeesRatio; + uint256 public stakeToFeesRatio; /// @notice The fees cut taken by the subgraph service mapping(IGraphPayments.PaymentTypes paymentType => ISubgraphService.PaymentCuts paymentCuts) public paymentCuts; diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 096d101a5..2c378809e 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -52,7 +52,7 @@ interface ISubgraphService is IDataServiceFees { * @notice Emitted when the stake to fees ratio is set. * @param ratio The stake to fees ratio */ - event StakeToFeesRatioSet(uint32 ratio); + event StakeToFeesRatioSet(uint256 ratio); /** * @notice Emmited when payment cuts are set for a payment type @@ -151,7 +151,7 @@ interface ISubgraphService is IDataServiceFees { * @notice Sets the stake to fees ratio * @param stakeToFeesRatio The stake to fees ratio */ - function setStakeToFeesRatio(uint32 stakeToFeesRatio) external; + function setStakeToFeesRatio(uint256 stakeToFeesRatio) external; /** * @notice Sets the max POI staleness diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index 1d07ec817..75ff738a8 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -12,7 +12,7 @@ abstract contract Constants { uint256 internal constant minimumProvisionTokens = 1000 ether; uint256 internal constant maximumProvisionTokens = type(uint256).max; uint32 internal constant delegationRatio = 16; - uint32 public constant stakeToFeesRatio = 2; + uint256 public constant stakeToFeesRatio = 2; uint256 public constant maxPOIStaleness = 28 days; uint128 public constant serviceCut = 10000; uint128 public constant curationCut = 10000; From 0f366d28b95ad1d25c1e351922b0ea82e9437320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 14 Aug 2024 15:42:36 -0300 Subject: [PATCH 142/277] fix: update subgraph endpoints to network and some linting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../subgraph-service/contracts/SubgraphService.sol | 12 ++++++++---- packages/subgraph-service/eslint.config.js | 2 +- packages/token-distribution/.env.sample | 1 + packages/token-distribution/.graphclientrc.yml | 4 ++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 0045b970d..d0db789b9 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -343,9 +343,9 @@ contract SubgraphService is /** * @notice See {ISubgraphService.setStakeToFeesRatio} */ - function setStakeToFeesRatio(uint256 _stakeToFeesRatio) external override onlyOwner { - stakeToFeesRatio = _stakeToFeesRatio; - emit StakeToFeesRatioSet(_stakeToFeesRatio); + function setStakeToFeesRatio(uint256 stakeToFeesRatio_) external override onlyOwner { + stakeToFeesRatio = stakeToFeesRatio_; + emit StakeToFeesRatioSet(stakeToFeesRatio_); } /** @@ -358,7 +358,11 @@ contract SubgraphService is /** * @notice See {ISubgraphService.setPaymentCuts} */ - function setPaymentCuts(IGraphPayments.PaymentTypes paymentType, uint128 serviceCut, uint128 curationCut) external override onlyOwner { + function setPaymentCuts( + IGraphPayments.PaymentTypes paymentType, + uint128 serviceCut, + uint128 curationCut + ) external override onlyOwner { paymentCuts[paymentType] = PaymentCuts(serviceCut, curationCut); emit PaymentCutsSet(paymentType, serviceCut, curationCut); } diff --git a/packages/subgraph-service/eslint.config.js b/packages/subgraph-service/eslint.config.js index 2cb4335fd..c9e06b116 100644 --- a/packages/subgraph-service/eslint.config.js +++ b/packages/subgraph-service/eslint.config.js @@ -16,6 +16,6 @@ module.exports = [ }, }, { - ignores: ['typechain-types/*'], + ignores: ['typechain-types/*', 'lib/*'], }, ] diff --git a/packages/token-distribution/.env.sample b/packages/token-distribution/.env.sample index 1ecb4d424..feae0f5fe 100644 --- a/packages/token-distribution/.env.sample +++ b/packages/token-distribution/.env.sample @@ -1,3 +1,4 @@ MNEMONIC= ETHERSCAN_API_KEY= INFURA_KEY= +STUDIO_API_KEY= diff --git a/packages/token-distribution/.graphclientrc.yml b/packages/token-distribution/.graphclientrc.yml index 34d67cb06..3ab12d3ca 100644 --- a/packages/token-distribution/.graphclientrc.yml +++ b/packages/token-distribution/.graphclientrc.yml @@ -2,13 +2,13 @@ sources: - name: graph-network handler: graphql: - endpoint: https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-mainnet + endpoint: https://gateway.thegraph.com/api/${STUDIO_API_KEY}/subgraphs/id/9Co7EQe5PgW3ugCUJrJgRv4u9zdEuDJf8NvMWftNsBH8 retry: 5 - name: token-distribution handler: graphql: - endpoint: https://api.thegraph.com/subgraphs/name/graphprotocol/token-distribution + endpoint: https://gateway.thegraph.com/api/${STUDIO_API_KEY}/subgraphs/id/ChfAJn6jQEBjVqtdUiThfG6sWy2Sr5XQPNucE9DkgXSN retry: 5 transforms: - autoPagination: From d0256329ac2669a0c7d6c7bef9c0795d1dfdffe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 15 Aug 2024 16:35:21 -0300 Subject: [PATCH 143/277] fix: add STUDIO_API_KEY to GitHub action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .github/workflows/ci-token-dist.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-token-dist.yml b/.github/workflows/ci-token-dist.yml index f45eb9111..c0e73b072 100644 --- a/.github/workflows/ci-token-dist.yml +++ b/.github/workflows/ci-token-dist.yml @@ -2,6 +2,7 @@ name: CI - packages/token-distribution env: CI: true + STUDIO_API_KEY: ${{ secrets.STUDIO_API_KEY }} on: push: From 8345a1f28e19cbe0d9c1bbf55f8fe764622827ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 15 Aug 2024 16:37:07 -0300 Subject: [PATCH 144/277] fix: missing env var declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62e6408fe..9536e68e3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,7 @@ name: Build env: CI: true + STUDIO_API_KEY: ${{ secrets.STUDIO_API_KEY }} on: push: From 5c5787a4ca5d344c0ec6dfb48af0843d5e70cd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 15 Aug 2024 17:02:59 -0300 Subject: [PATCH 145/277] ci: build packages individudally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .github/actions/setup/action.yml | 3 --- .github/workflows/build.yml | 4 +++- .github/workflows/ci-contracts.yml | 4 ++++ .github/workflows/ci-data-edge.yml | 4 ++++ .github/workflows/ci-horizon.yml | 4 ++++ .github/workflows/ci-subgraph-service.yml | 4 ++++ .github/workflows/ci-token-dist.yml | 4 ++++ .github/workflows/e2e-contracts.yml | 4 ++++ .github/workflows/verifydeployed.yml | 10 ++++++++-- 9 files changed, 35 insertions(+), 6 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index baeec7b27..310c412bd 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -17,6 +17,3 @@ runs: - name: Install dependencies shell: bash run: yarn --immutable - - name: Build - shell: bash - run: yarn build || yarn build diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9536e68e3..2a7a8b2ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,4 +20,6 @@ jobs: with: submodules: recursive - name: Set up environment - uses: ./.github/actions/setup \ No newline at end of file + uses: ./.github/actions/setup + - name: Build + run: yarn build || yarn build \ No newline at end of file diff --git a/.github/workflows/ci-contracts.yml b/.github/workflows/ci-contracts.yml index 7dca1bfde..d60ab0d9b 100644 --- a/.github/workflows/ci-contracts.yml +++ b/.github/workflows/ci-contracts.yml @@ -24,6 +24,10 @@ jobs: submodules: recursive - name: Set up environment uses: ./.github/actions/setup + - name: Build + run: | + pushd packages/contracts + yarn build || yarn build - name: Run tests run: | pushd packages/contracts diff --git a/.github/workflows/ci-data-edge.yml b/.github/workflows/ci-data-edge.yml index 065e0f964..a8046aa7e 100644 --- a/.github/workflows/ci-data-edge.yml +++ b/.github/workflows/ci-data-edge.yml @@ -22,5 +22,9 @@ jobs: uses: actions/checkout@v4 - name: Set up environment uses: ./.github/actions/setup + - name: Build + run: | + pushd packages/data-edge + yarn build - name: Run tests run: yarn test \ No newline at end of file diff --git a/.github/workflows/ci-horizon.yml b/.github/workflows/ci-horizon.yml index d450d1264..159ca7b4d 100644 --- a/.github/workflows/ci-horizon.yml +++ b/.github/workflows/ci-horizon.yml @@ -24,6 +24,10 @@ jobs: submodules: recursive - name: Set up environment uses: ./.github/actions/setup + - name: Build + run: | + pushd packages/horizon + yarn build - name: Run tests run: | pushd packages/horizon diff --git a/.github/workflows/ci-subgraph-service.yml b/.github/workflows/ci-subgraph-service.yml index bda15deff..141c3549d 100644 --- a/.github/workflows/ci-subgraph-service.yml +++ b/.github/workflows/ci-subgraph-service.yml @@ -24,6 +24,10 @@ jobs: submodules: recursive - name: Set up environment uses: ./.github/actions/setup + - name: Build + run: | + pushd packages/subgraph-service + yarn build - name: Run tests run: | pushd packages/subgraph-service diff --git a/.github/workflows/ci-token-dist.yml b/.github/workflows/ci-token-dist.yml index c0e73b072..b991c1608 100644 --- a/.github/workflows/ci-token-dist.yml +++ b/.github/workflows/ci-token-dist.yml @@ -25,6 +25,10 @@ jobs: submodules: recursive - name: Set up environment uses: ./.github/actions/setup + - name: Build + run: | + pushd packages/token-distribution + yarn build - name: Run tests run: | pushd packages/token-distribution diff --git a/.github/workflows/e2e-contracts.yml b/.github/workflows/e2e-contracts.yml index c84adb1a0..ce5540add 100644 --- a/.github/workflows/e2e-contracts.yml +++ b/.github/workflows/e2e-contracts.yml @@ -34,6 +34,10 @@ jobs: submodules: recursive - name: Set up environment uses: ./.github/actions/setup + - name: Build + run: | + pushd packages/contracts + yarn build || yarn build - name: Run e2e tests run: | git clone https://github.com/OffchainLabs/nitro-testnode/ diff --git a/.github/workflows/verifydeployed.yml b/.github/workflows/verifydeployed.yml index 9de43994c..db5b90133 100644 --- a/.github/workflows/verifydeployed.yml +++ b/.github/workflows/verifydeployed.yml @@ -30,8 +30,10 @@ jobs: - name: Set up environment uses: ./.github/actions/setup - - name: Compile contracts - run: yarn build + - name: Build + run: | + pushd packages/contracts + yarn build || yarn build - name: Save build artifacts uses: actions/upload-artifact@v3 @@ -50,6 +52,10 @@ jobs: uses: actions/checkout@v3 - name: Set up environment uses: ./.github/actions/setup + - name: Build + run: | + pushd packages/contracts + yarn build || yarn build - name: Get build artifacts uses: actions/download-artifact@v3 with: From 4bdd2375532129302768ede8437942eac0de19ec Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 7 Aug 2024 15:13:48 -0300 Subject: [PATCH 146/277] fix: addToDelegationPool access control and token transfer (OZ C-01) --- .../internal/IHorizonStakingMain.sol | 6 ++ .../horizon/contracts/mocks/MockGRTToken.sol | 4 +- .../contracts/payments/GraphPayments.sol | 1 + .../contracts/staking/HorizonStaking.sol | 2 + packages/horizon/test/escrow/collect.t.sol | 2 +- .../test/staking/allocation/collect.t.sol | 1 + .../test/staking/delegation/addToPool.t.sol | 79 +++++++++++++++++++ 7 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 packages/horizon/test/staking/delegation/addToPool.t.sol diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index a6f18c66c..ede817cb8 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -338,6 +338,12 @@ interface IHorizonStakingMain { */ error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); + /** + * @notice Thrown when an unauthorized sender attempts to deposit tokens into the delegation pool. + * @param sender The message sender address + */ + error HorizonStakingInvalidDelegationPoolSender(address sender); + /** * @notice Thrown when attempting to create a provision with an invalid maximum verifier cut. * @param maxVerifierCut The maximum verifier cut diff --git a/packages/horizon/contracts/mocks/MockGRTToken.sol b/packages/horizon/contracts/mocks/MockGRTToken.sol index 1a51f3b96..1d5649f29 100644 --- a/packages/horizon/contracts/mocks/MockGRTToken.sol +++ b/packages/horizon/contracts/mocks/MockGRTToken.sol @@ -7,7 +7,9 @@ import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToke contract MockGRTToken is ERC20, IGraphToken { constructor() ERC20("Graph Token", "GRT") {} - function burn(uint256 tokens) external {} + function burn(uint256 tokens) external { + _burn(msg.sender, tokens); + } function burnFrom(address from, uint256 tokens) external { _burn(from, tokens); diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 298a1a74c..0deb8d112 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -68,6 +68,7 @@ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, I // Pay delegators if (tokensDelegationPool > 0) { + _graphToken().approve(address(_graphStaking()), tokensDelegationPool); _graphStaking().addToDelegationPool(receiver, dataService, tokensDelegationPool); } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 6b02c86c8..731efaf08 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -278,6 +278,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokens ) external override notPaused { require(tokens != 0, HorizonStakingInvalidZeroTokens()); + require(msg.sender == verifier || msg.sender == address(_graphPayments()), HorizonStakingInvalidDelegationPoolSender(msg.sender)); + _graphToken().pullTokens(msg.sender, tokens); DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); pool.tokens = pool.tokens + tokens; emit TokensToDelegationPoolAdded(serviceProvider, verifier, tokens); diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index ab6808f55..baa1de06e 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -31,7 +31,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { uint256 indexerBalance = token.balanceOf(users.indexer); uint256 indexerExpectedPayment = amount - tokensDataService - tokensProtocol - tokensDelegatoion; assertEq(indexerBalance - indexerPreviousBalance, indexerExpectedPayment); - assertTrue(true); + assertEq(token.balanceOf(address(payments)), 0); } function testCollect_RevertWhen_CollectorNotAuthorized(uint256 amount) public { diff --git a/packages/horizon/test/staking/allocation/collect.t.sol b/packages/horizon/test/staking/allocation/collect.t.sol index b12783510..43c3c67ca 100644 --- a/packages/horizon/test/staking/allocation/collect.t.sol +++ b/packages/horizon/test/staking/allocation/collect.t.sol @@ -141,6 +141,7 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { assertEq(staking.getStake(address(users.indexer)), provisionTokens + payment); assertEq(curation.curation(_subgraphDeploymentID), curationTokens + curationCutTokens); assertEq(staking.getDelegationPool(users.indexer, subgraphDataServiceLegacyAddress).tokens, delegationTokens + delegationFeeCut); + assertEq(token.balanceOf(address(payments)), 0); } function testCollect_WithBeneficiaryAddress( diff --git a/packages/horizon/test/staking/delegation/addToPool.t.sol b/packages/horizon/test/staking/delegation/addToPool.t.sol new file mode 100644 index 000000000..6335de7a9 --- /dev/null +++ b/packages/horizon/test/staking/delegation/addToPool.t.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { + + modifier useValidDelegationAmount(uint256 tokens) { + vm.assume(tokens > 0); + vm.assume(tokens <= MAX_STAKING_TOKENS); + _; + } + + /* + * TESTS + */ + + function test_Delegation_AddToPool_Verifier( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) { + uint256 stakingPreviousBalance = token.balanceOf(address(staking)); + + resetPrank(subgraphDataServiceAddress); + mint(subgraphDataServiceAddress, delegationAmount); + token.approve(address(staking), delegationAmount); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.TokensToDelegationPoolAdded(users.indexer, subgraphDataServiceAddress, delegationAmount); + staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); + + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(delegatedTokens, delegationAmount); + assertEq(token.balanceOf(subgraphDataServiceAddress), 0); + assertEq(token.balanceOf(address(staking)), stakingPreviousBalance + delegationAmount); + } + + function test_Delegation_AddToPool_Payments( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) { + uint256 stakingPreviousBalance = token.balanceOf(address(staking)); + + resetPrank(address(payments)); + mint(address(payments), delegationAmount); + token.approve(address(staking), delegationAmount); + staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); + + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(delegatedTokens, delegationAmount); + assertEq(token.balanceOf(subgraphDataServiceAddress), 0); + assertEq(token.balanceOf(address(staking)), stakingPreviousBalance + delegationAmount); + } + + function test_Delegation_AddToPool_RevertWhen_InvalidSender( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) { + vm.assume(delegationAmount > 0); + vm.startPrank(users.delegator); + bytes memory expectedError = abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolSender.selector, + users.delegator + ); + vm.expectRevert(expectedError); + staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); + } + + function test_Delegation_AddToPool_RevertWhen_ZeroTokens( + uint256 amount + ) public useIndexer useProvision(amount, 0, 0) { + vm.startPrank(subgraphDataServiceAddress); + bytes memory expectedError = abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingInvalidZeroTokens.selector); + vm.expectRevert(expectedError); + staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 0); + } +} \ No newline at end of file From f4f9badb7d72547142e45c57e5f259fdf27d2b2e Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 13 Aug 2024 15:01:43 -0300 Subject: [PATCH 147/277] fix: moved pull tokens and made addToDelegationPool open to all --- .../interfaces/internal/IHorizonStakingMain.sol | 7 +------ .../horizon/contracts/staking/HorizonStaking.sol | 3 +-- .../test/staking/delegation/addToPool.t.sol | 14 -------------- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index ede817cb8..2f45ef386 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -338,12 +338,6 @@ interface IHorizonStakingMain { */ error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); - /** - * @notice Thrown when an unauthorized sender attempts to deposit tokens into the delegation pool. - * @param sender The message sender address - */ - error HorizonStakingInvalidDelegationPoolSender(address sender); - /** * @notice Thrown when attempting to create a provision with an invalid maximum verifier cut. * @param maxVerifierCut The maximum verifier cut @@ -667,6 +661,7 @@ interface IHorizonStakingMain { * * @dev Requirements: * - `tokens` cannot be zero. + * - Caller must have previously approved this contract to pull tokens from their balance. * * Emits a {TokensToDelegationPoolAdded} event. * diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 731efaf08..6ad6dec7c 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -278,10 +278,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokens ) external override notPaused { require(tokens != 0, HorizonStakingInvalidZeroTokens()); - require(msg.sender == verifier || msg.sender == address(_graphPayments()), HorizonStakingInvalidDelegationPoolSender(msg.sender)); - _graphToken().pullTokens(msg.sender, tokens); DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); pool.tokens = pool.tokens + tokens; + _graphToken().pullTokens(msg.sender, tokens); emit TokensToDelegationPoolAdded(serviceProvider, verifier, tokens); } diff --git a/packages/horizon/test/staking/delegation/addToPool.t.sol b/packages/horizon/test/staking/delegation/addToPool.t.sol index 6335de7a9..bdafa4046 100644 --- a/packages/horizon/test/staking/delegation/addToPool.t.sol +++ b/packages/horizon/test/staking/delegation/addToPool.t.sol @@ -54,20 +54,6 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { assertEq(token.balanceOf(address(staking)), stakingPreviousBalance + delegationAmount); } - function test_Delegation_AddToPool_RevertWhen_InvalidSender( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) { - vm.assume(delegationAmount > 0); - vm.startPrank(users.delegator); - bytes memory expectedError = abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidDelegationPoolSender.selector, - users.delegator - ); - vm.expectRevert(expectedError); - staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); - } - function test_Delegation_AddToPool_RevertWhen_ZeroTokens( uint256 amount ) public useIndexer useProvision(amount, 0, 0) { From a183d7ed952165bb23c0eaa9efa12fefeea807f9 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 8 Aug 2024 15:23:36 -0300 Subject: [PATCH 148/277] fix: add subgraph service as a caller when collecting from curation contract (OZ C-03) --- .../contracts/curation/CurationStorage.sol | 13 +++++++ .../contracts/l2/curation/IL2Curation.sol | 6 +++ .../contracts/l2/curation/L2Curation.sol | 23 ++++++++++-- .../contracts/test/unit/l2/l2Curation.test.ts | 37 ++++++++++++++++--- 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/packages/contracts/contracts/curation/CurationStorage.sol b/packages/contracts/contracts/curation/CurationStorage.sol index bcbf0df6b..12f5b255b 100644 --- a/packages/contracts/contracts/curation/CurationStorage.sol +++ b/packages/contracts/contracts/curation/CurationStorage.sol @@ -68,3 +68,16 @@ abstract contract CurationV1Storage is Managed, ICuration { abstract contract CurationV2Storage is CurationV1Storage, Initializable { // Nothing here, just adding Initializable } + +/** + * @title Curation Storage version 3 + * @dev This contract holds the third version of the storage variables + * for the Curation and L2Curation contracts. + * It adds a new variable subgraphService to the storage. + * When adding new variables, create a new version that inherits this and update + * the contracts to use the new version instead. + */ +abstract contract CurationV3Storage is CurationV2Storage { + // Address of the subgraph service + address public subgraphService; +} diff --git a/packages/contracts/contracts/l2/curation/IL2Curation.sol b/packages/contracts/contracts/l2/curation/IL2Curation.sol index bbbfd82ff..b59960792 100644 --- a/packages/contracts/contracts/l2/curation/IL2Curation.sol +++ b/packages/contracts/contracts/l2/curation/IL2Curation.sol @@ -6,6 +6,12 @@ pragma solidity ^0.7.6; * @title Interface of the L2 Curation contract. */ interface IL2Curation { + /** + * @notice Set the subgraph service address. + * @param _subgraphService Address of the SubgraphService contract + */ + function setSubgraphService(address _subgraphService) external; + /** * @notice Deposit Graph Tokens in exchange for signal of a SubgraphDeployment curation pool. * @dev This function charges no tax and can only be called by GNS in specific scenarios (for now diff --git a/packages/contracts/contracts/l2/curation/L2Curation.sol b/packages/contracts/contracts/l2/curation/L2Curation.sol index 4d51bf3f1..efc690bb0 100644 --- a/packages/contracts/contracts/l2/curation/L2Curation.sol +++ b/packages/contracts/contracts/l2/curation/L2Curation.sol @@ -12,7 +12,7 @@ import { TokenUtils } from "../../utils/TokenUtils.sol"; import { IRewardsManager } from "../../rewards/IRewardsManager.sol"; import { Managed } from "../../governance/Managed.sol"; import { IGraphToken } from "../../token/IGraphToken.sol"; -import { CurationV2Storage } from "../../curation/CurationStorage.sol"; +import { CurationV3Storage } from "../../curation/CurationStorage.sol"; import { IGraphCurationToken } from "../../curation/IGraphCurationToken.sol"; import { IL2Curation } from "./IL2Curation.sol"; @@ -28,7 +28,7 @@ import { IL2Curation } from "./IL2Curation.sol"; * Holders can burn GCS using this contract to get GRT tokens back according to the * bonding curve. */ -contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { +contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { using SafeMathUpgradeable for uint256; /// @dev 100% in parts per million @@ -67,6 +67,11 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { */ event Collected(bytes32 indexed subgraphDeploymentID, uint256 tokens); + /** + * @dev Emitted when the subgraph service is set. + */ + event SubgraphServiceSet(address indexed oldSubgraphService, address indexed newSubgraphService); + /** * @dev Modifier for functions that can only be called by the GNS contract */ @@ -131,6 +136,16 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { _setCurationTokenMaster(_curationTokenMaster); } + /** + * @notice Set the subgraph service address + * @param _subgraphService Address of the subgraph service contract + */ + function setSubgraphService(address _subgraphService) external override onlyGovernor { + address oldSubgraphService = subgraphService; + subgraphService = _subgraphService; + emit SubgraphServiceSet(oldSubgraphService, _subgraphService); + } + /** * @notice Assign Graph Tokens collected as curation fees to the curation pool reserve. * @dev This function can only be called by the Staking contract and will do the bookeeping of @@ -139,8 +154,8 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _tokens Amount of Graph Tokens to add to reserves */ function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external override { - // Only Staking contract is authorized as caller - require(msg.sender == address(staking()), "Caller must be the staking contract"); + // Only SubgraphService or Staking contract are authorized as caller + require(msg.sender == subgraphService || msg.sender == address(staking()), "Caller must be the subgraph service or staking contract"); // Must be curated to accept tokens require(isCurated(_subgraphDeploymentID), "Subgraph deployment must be curated to collect fees"); diff --git a/packages/contracts/test/unit/l2/l2Curation.test.ts b/packages/contracts/test/unit/l2/l2Curation.test.ts index f004318f1..29ac28319 100644 --- a/packages/contracts/test/unit/l2/l2Curation.test.ts +++ b/packages/contracts/test/unit/l2/l2Curation.test.ts @@ -150,6 +150,20 @@ describe('L2Curation:Config', () => { await expect(tx).revertedWith('Only Controller governor') }) }) + + describe('subgraphService', function () { + it('should set `subgraphService`', async function () { + const newSubgraphService = randomAddress() + await curation.connect(governor).setSubgraphService(newSubgraphService) + expect(await curation.subgraphService()).eq(newSubgraphService) + }) + + it('reject set `subgraphService` if not allowed', async function () { + const newSubgraphService = randomAddress() + const tx = curation.connect(me).setSubgraphService(newSubgraphService) + await expect(tx).revertedWith('Only Controller governor') + }) + }) }) describe('L2Curation', () => { @@ -158,6 +172,7 @@ describe('L2Curation', () => { let governor: SignerWithAddress let curator: SignerWithAddress let stakingMock: SignerWithAddress + let subgraphService: SignerWithAddress let gnsImpersonator: Signer let fixture: NetworkFixture @@ -322,14 +337,14 @@ describe('L2Curation', () => { expect(afterTokenTotalSupply).eq(beforeTokenTotalSupply) } - const shouldCollect = async (tokensToCollect: BigNumber) => { + const shouldCollect = async (tokensToCollect: BigNumber, signer: SignerWithAddress = stakingMock) => { // Before state const beforePool = await curation.pools(subgraphDeploymentID) const beforeTotalBalance = await grt.balanceOf(curation.address) // Source of tokens must be the staking for this to work - await grt.connect(stakingMock).transfer(curation.address, tokensToCollect) - const tx = curation.connect(stakingMock).collect(subgraphDeploymentID, tokensToCollect) + await grt.connect(signer).transfer(curation.address, tokensToCollect) + const tx = curation.connect(signer).collect(subgraphDeploymentID, tokensToCollect) await expect(tx).emit(curation, 'Collected').withArgs(subgraphDeploymentID, tokensToCollect) // After state @@ -343,7 +358,7 @@ describe('L2Curation', () => { before(async function () { // Use stakingMock so we can call collect - [me, curator, stakingMock] = await graph.getTestAccounts() + [me, curator, stakingMock, subgraphService] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor, true) @@ -576,10 +591,10 @@ describe('L2Curation', () => { it('reject collect tokens distributed from invalid address', async function () { const tx = curation.connect(me).collect(subgraphDeploymentID, tokensToCollect) - await expect(tx).revertedWith('Caller must be the staking contract') + await expect(tx).revertedWith('Caller must be the subgraph service or staking contract') }) - it('should collect tokens distributed to the curation pool', async function () { + it('should collect tokens distributed to the curation pool from staking contract', async function () { await controller .connect(governor) .setContractProxy(utils.id('Staking'), stakingMock.address) @@ -592,6 +607,16 @@ describe('L2Curation', () => { await shouldCollect(toGRT('500.25')) }) + it('should collect tokens distributed to the curation pool from subgraph service address', async function () { + await grt.connect(governor).mint(subgraphService.address, tokensToCollect) + await curation.connect(governor).setSubgraphService(subgraphService.address) + await shouldCollect(toGRT('1'), subgraphService) + await shouldCollect(toGRT('10'), subgraphService) + await shouldCollect(toGRT('100'), subgraphService) + await shouldCollect(toGRT('200'), subgraphService) + await shouldCollect(toGRT('500.25'), subgraphService) + }) + it('should collect tokens and then unsignal all', async function () { await controller .connect(governor) From e0cf705efa5e466fdc04eb0ec4c7425d85c8c007 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 8 Aug 2024 19:33:52 -0300 Subject: [PATCH 149/277] fix: subgraphService access controll (OZ C-04) --- .../contracts/SubgraphService.sol | 9 ++- .../contracts/interfaces/ISubgraphService.sol | 7 +++ .../contracts/utilities/AllocationManager.sol | 11 +++- .../subgraphService/SubgraphService.t.sol | 16 +++++ .../test/subgraphService/allocate/stop.t.sol | 15 +++++ .../subgraphService/collect/collect.t.sol | 58 +++++++++++++++++-- 6 files changed, 108 insertions(+), 8 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index d0db789b9..b2f3940d0 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -221,6 +221,7 @@ contract SubgraphService is bytes calldata data ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { address allocationId = abi.decode(data, (address)); + require(allocations[allocationId].indexer == indexer, SubgraphServiceIndexerNotAuthorized(indexer, allocationId)); _closeAllocation(allocationId); emit ServiceStopped(indexer, data); } @@ -250,13 +251,13 @@ contract SubgraphService is address indexer, IGraphPayments.PaymentTypes paymentType, bytes calldata data - ) external override onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + ) external override onlyProvisionAuthorized(indexer) onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { uint256 paymentCollected = 0; if (paymentType == IGraphPayments.PaymentTypes.QueryFee) { paymentCollected = _collectQueryFees(data); } else if (paymentType == IGraphPayments.PaymentTypes.IndexingRewards) { - paymentCollected = _collectIndexingRewards(data); + paymentCollected = _collectIndexingRewards(indexer, data); } else { revert SubgraphServiceInvalidPaymentType(paymentType); } @@ -488,7 +489,9 @@ contract SubgraphService is ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); address indexer = signedRav.rav.serviceProvider; address allocationId = abi.decode(signedRav.rav.metadata, (address)); - bytes32 subgraphDeploymentId = allocations.get(allocationId).subgraphDeploymentId; + Allocation.State memory allocation = allocations.get(allocationId); + require(allocation.indexer == indexer, SubgraphServiceIndexerNotAuthorized(indexer, allocationId)); + bytes32 subgraphDeploymentId = allocation.subgraphDeploymentId; // release expired stake claims _releaseStake(indexer, 0); diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 2c378809e..cdb07c35e 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -93,6 +93,13 @@ interface ISubgraphService is IDataServiceFees { */ error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); + /** + * @notice Thrown when an indexer tries to perform an operation but they are not authorized + * @param indexer The address of the indexer + * @param allocationId The id of the allocation + */ + error SubgraphServiceIndexerNotAuthorized(address indexer, address allocationId); + /** * @notice Initialize the contract * @param minimumProvisionTokens The minimum amount of provisioned tokens required to create an allocation diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 850b3fd13..27aa47ce2 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -152,6 +152,13 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca */ error AllocationManagerAllocationSameSize(address allocationId, uint256 tokens); + /** + * @notice Thrown when an indexer is not allocation owner + * @param allocationId The id of the allocation + * @param indexer The address of the indexer + */ + error AllocationManagerIndexerNotAuthorized(address indexer, address allocationId); + /** * @notice Initializes the contract and parent contracts */ @@ -250,14 +257,16 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * * Emits a {IndexingRewardsCollected} event. * + * @param indexer The address of the indexer * @param _data Encoded data containing: * - address `allocationId`: The id of the allocation to collect rewards for * - bytes32 `poi`: The POI being presented */ - function _collectIndexingRewards(bytes memory _data) internal returns (uint256) { + function _collectIndexingRewards(address indexer, bytes memory _data) internal returns (uint256) { (address allocationId, bytes32 poi) = abi.decode(_data, (address, bytes32)); Allocation.State memory allocation = allocations.get(allocationId); + require(allocation.indexer == indexer, AllocationManagerIndexerNotAuthorized(indexer, allocationId)); require(allocation.isOpen(), AllocationManagerAllocationClosed(allocationId)); // Mint indexing rewards if all conditions are met diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 65498e485..f0bc41c58 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -33,4 +33,20 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { * HELPERS */ + function _createAndStartAllocation(address indexer, uint256 tokens) internal { + mint(indexer, tokens); + + resetPrank(indexer); + token.approve(address(staking), tokens); + staking.stakeTo(indexer, tokens); + staking.provision(indexer, address(subgraphService), tokens, maxSlashingPercentage, disputePeriod); + subgraphService.register(indexer, abi.encode("url", "geoHash", address(0))); + + (address newIndexerAllocationId, uint256 newIndexerAllocationKey) = makeAddrAndKey("newIndexerAllocationId"); + bytes32 digest = subgraphService.encodeAllocationProof(indexer, newIndexerAllocationId); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(newIndexerAllocationKey, digest); + + bytes memory data = abi.encode(subgraphDeployment, tokens, newIndexerAllocationId, abi.encodePacked(r, s, v)); + subgraphService.startService(indexer, data); + } } diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index 06a2019ec..761a9a938 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -34,6 +34,21 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { assertEq(subgraphAllocatedTokens, 0); } + function testStop_RevertWhen_IndexerIsNotTheAllocationOwner(uint256 tokens) public useIndexer useAllocation(tokens) { + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + + // Attempt to close other indexer's allocation + bytes memory data = abi.encode(allocationID); + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceIndexerNotAuthorized.selector, + newIndexer, + allocationID + )); + subgraphService.stopService(newIndexer, data); + } + function testStop_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { resetPrank(users.operator); bytes memory data = abi.encode(allocationID); diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index 0683c4712..a83fa8a58 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -9,6 +9,7 @@ import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPC import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; @@ -24,9 +25,10 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { */ function _getQueryFeeEncodedData( + address indexer, uint128 tokens ) private view returns (bytes memory) { - ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(tokens); + ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(indexer, tokens); bytes32 messageHash = tapCollector.encodeRAV(rav); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, messageHash); bytes memory signature = abi.encodePacked(r, s, v); @@ -34,10 +36,10 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { return abi.encode(signedRAV); } - function _getRAV(uint128 tokens) private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { + function _getRAV(address indexer, uint128 tokens) private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { return ITAPCollector.ReceiptAggregateVoucher({ dataService: address(subgraphService), - serviceProvider: users.indexer, + serviceProvider: indexer, timestampNs: 0, valueAggregate: tokens, metadata: abi.encode(allocationID) @@ -78,7 +80,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { tokensPayment = bound(tokensPayment, minimumProvisionTokens, maxTokensPayment); uint128 tokensPayment128 = uint128(tokensPayment); IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; - bytes memory data = _getQueryFeeEncodedData(tokensPayment128); + bytes memory data = _getQueryFeeEncodedData(users.indexer, tokensPayment128); uint256 indexerPreviousBalance = token.balanceOf(users.indexer); @@ -115,4 +117,52 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { )); subgraphService.collect(users.indexer, invalidPaymentType, ""); } + + function testCollect_RevertWhen_NotAuthorized( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); + resetPrank(users.operator); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + )); + subgraphService.collect(users.indexer, paymentType, data); + } + + function testCollect_QueryFees_RevertWhen_IndexerIsNotAllocationOwner( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + bytes memory data = _getQueryFeeEncodedData(newIndexer, uint128(tokens)); + // Attempt to collect from other indexer's allocation + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceIndexerNotAuthorized.selector, + newIndexer, + allocationID + )); + subgraphService.collect(newIndexer, paymentType, data); + } + + function testCollect_IndexingFees_RevertWhen_IndexerIsNotAllocationOwner( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + bytes memory data = abi.encode(allocationID, bytes32("POI1")); + // Attempt to collect from other indexer's allocation + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerIndexerNotAuthorized.selector, + newIndexer, + allocationID + )); + subgraphService.collect(newIndexer, paymentType, data); + } } From 857f27b75db2051dc8f52592c1b812d338fe57b3 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 9 Aug 2024 17:33:39 -0300 Subject: [PATCH 150/277] fix: collecting other indexers query fees --- .../contracts/SubgraphService.sol | 11 ++++++----- .../contracts/interfaces/ISubgraphService.sol | 14 ++++++++++---- .../test/subgraphService/allocate/stop.t.sol | 5 ++--- .../test/subgraphService/collect/collect.t.sol | 18 ++++++++++++++++-- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index b2f3940d0..0ba7c3ccd 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -221,7 +221,7 @@ contract SubgraphService is bytes calldata data ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { address allocationId = abi.decode(data, (address)); - require(allocations[allocationId].indexer == indexer, SubgraphServiceIndexerNotAuthorized(indexer, allocationId)); + require(allocations[allocationId].indexer == indexer, SubgraphServiceInvalidIndexer(indexer)); _closeAllocation(allocationId); emit ServiceStopped(indexer, data); } @@ -255,7 +255,7 @@ contract SubgraphService is uint256 paymentCollected = 0; if (paymentType == IGraphPayments.PaymentTypes.QueryFee) { - paymentCollected = _collectQueryFees(data); + paymentCollected = _collectQueryFees(indexer, data); } else if (paymentType == IGraphPayments.PaymentTypes.IndexingRewards) { paymentCollected = _collectIndexingRewards(indexer, data); } else { @@ -485,12 +485,13 @@ contract SubgraphService is * * @param _data Encoded data containing a signed RAV */ - function _collectQueryFees(bytes memory _data) private returns (uint256 feesCollected) { + function _collectQueryFees(address indexer, bytes memory _data) private returns (uint256 feesCollected) { ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); - address indexer = signedRav.rav.serviceProvider; + address serviceProvider = signedRav.rav.serviceProvider; + require(indexer == serviceProvider, SubgraphServiceInvalidIndexer(indexer)); address allocationId = abi.decode(signedRav.rav.metadata, (address)); Allocation.State memory allocation = allocations.get(allocationId); - require(allocation.indexer == indexer, SubgraphServiceIndexerNotAuthorized(indexer, allocationId)); + require(allocation.indexer == indexer, SubgraphServiceInvalidAllocationIndexer(indexer, allocationId)); bytes32 subgraphDeploymentId = allocation.subgraphDeploymentId; // release expired stake claims diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index cdb07c35e..594fa0865 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -94,11 +94,17 @@ interface ISubgraphService is IDataServiceFees { error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); /** - * @notice Thrown when an indexer tries to perform an operation but they are not authorized - * @param indexer The address of the indexer - * @param allocationId The id of the allocation + * @notice @notice Thrown when the service provider in the RAV does not match the expected indexer. + * @param indexer The address of the expected indexer. + */ + error SubgraphServiceInvalidIndexer(address indexer); + + /** + * @notice Thrown when the indexer in the allocation state does not match the expected indexer. + * @param indexer The address of the expected indexer. + * @param allocationId The id of the allocation. */ - error SubgraphServiceIndexerNotAuthorized(address indexer, address allocationId); + error SubgraphServiceInvalidAllocationIndexer(address indexer, address allocationId); /** * @notice Initialize the contract diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index 761a9a938..cf1b20dca 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -42,9 +42,8 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { // Attempt to close other indexer's allocation bytes memory data = abi.encode(allocationID); vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceIndexerNotAuthorized.selector, - newIndexer, - allocationID + ISubgraphService.SubgraphServiceInvalidIndexer.selector, + newIndexer )); subgraphService.stopService(newIndexer, data); } diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index a83fa8a58..5c4a67834 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -140,15 +140,29 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { address newIndexer = makeAddr("newIndexer"); _createAndStartAllocation(newIndexer, tokens); bytes memory data = _getQueryFeeEncodedData(newIndexer, uint128(tokens)); - // Attempt to collect from other indexer's allocation vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceIndexerNotAuthorized.selector, + ISubgraphService.SubgraphServiceInvalidAllocationIndexer.selector, newIndexer, allocationID )); subgraphService.collect(newIndexer, paymentType, data); } + function testCollect_QueryFees_RevertWhen_CollectingOtherIndexersFees( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceInvalidIndexer.selector, + newIndexer + )); + subgraphService.collect(newIndexer, paymentType, data); + } + function testCollect_IndexingFees_RevertWhen_IndexerIsNotAllocationOwner( uint256 tokens ) public useIndexer useAllocation(tokens) { From 0364b4115f233cbff44749652d78c786a853675c Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 13 Aug 2024 14:31:11 -0300 Subject: [PATCH 151/277] fix: renaming errors and variables --- .../contracts/SubgraphService.sol | 20 +++++++++++-------- .../contracts/interfaces/ISubgraphService.sol | 7 ++++--- .../contracts/utilities/AllocationManager.sol | 8 ++++---- .../test/subgraphService/allocate/stop.t.sol | 5 +++-- .../subgraphService/collect/collect.t.sol | 9 +++++---- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 0ba7c3ccd..1833515c4 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -221,7 +221,7 @@ contract SubgraphService is bytes calldata data ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { address allocationId = abi.decode(data, (address)); - require(allocations[allocationId].indexer == indexer, SubgraphServiceInvalidIndexer(indexer)); + require(allocations[allocationId].indexer == indexer, SubgraphServiceAllocationNotAuthorized(indexer, allocationId)); _closeAllocation(allocationId); emit ServiceStopped(indexer, data); } @@ -483,19 +483,23 @@ contract SubgraphService is * Emits a {StakeClaimLocked} event. * Emits a {QueryFeesCollected} event. * + * @param _indexer The address of the indexer * @param _data Encoded data containing a signed RAV */ - function _collectQueryFees(address indexer, bytes memory _data) private returns (uint256 feesCollected) { + function _collectQueryFees(address _indexer, bytes memory _data) private returns (uint256 feesCollected) { ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); - address serviceProvider = signedRav.rav.serviceProvider; - require(indexer == serviceProvider, SubgraphServiceInvalidIndexer(indexer)); + address indexer = signedRav.rav.serviceProvider; + require(_indexer == indexer, SubgraphServiceIndexerMismatch(indexer, _indexer)); address allocationId = abi.decode(signedRav.rav.metadata, (address)); Allocation.State memory allocation = allocations.get(allocationId); - require(allocation.indexer == indexer, SubgraphServiceInvalidAllocationIndexer(indexer, allocationId)); + + // Not strictly necessary: if an indexer collects another's voucher, they lock their stake with no gains. + // We include the check to guard against potential malicious payers deceiving the indexer. + require(allocation.indexer == _indexer, SubgraphServiceAllocationNotAuthorized(_indexer, allocationId)); bytes32 subgraphDeploymentId = allocation.subgraphDeploymentId; // release expired stake claims - _releaseStake(indexer, 0); + _releaseStake(_indexer, 0); // Collect from GraphPayments PaymentCuts memory queryFeePaymentCuts = _getQueryFeePaymentCuts(subgraphDeploymentId); @@ -519,7 +523,7 @@ contract SubgraphService is // lock stake as economic security for fees uint256 tokensToLock = tokensCollected * stakeToFeesRatio; uint256 unlockTimestamp = block.timestamp + _disputeManager().getDisputePeriod(); - _lockStake(indexer, tokensToLock, unlockTimestamp); + _lockStake(_indexer, tokensToLock, unlockTimestamp); // calculate service and curator cuts tokensCurators = tokensCollected.mulPPMRoundUp(queryFeePaymentCuts.curationCut); @@ -535,7 +539,7 @@ contract SubgraphService is } } - emit QueryFeesCollected(indexer, tokensCollected, tokensCurators, tokensSubgraphService); + emit QueryFeesCollected(_indexer, tokensCollected, tokensCurators, tokensSubgraphService); return tokensCollected; } diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 594fa0865..4cceee6b0 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -95,16 +95,17 @@ interface ISubgraphService is IDataServiceFees { /** * @notice @notice Thrown when the service provider in the RAV does not match the expected indexer. - * @param indexer The address of the expected indexer. + * @param providedIndexer The address of the provided indexer. + * @param expectedIndexer The address of the expected indexer. */ - error SubgraphServiceInvalidIndexer(address indexer); + error SubgraphServiceIndexerMismatch(address providedIndexer, address expectedIndexer); /** * @notice Thrown when the indexer in the allocation state does not match the expected indexer. * @param indexer The address of the expected indexer. * @param allocationId The id of the allocation. */ - error SubgraphServiceInvalidAllocationIndexer(address indexer, address allocationId); + error SubgraphServiceAllocationNotAuthorized(address indexer, address allocationId); /** * @notice Initialize the contract diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 27aa47ce2..bf6165272 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -157,7 +157,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * @param allocationId The id of the allocation * @param indexer The address of the indexer */ - error AllocationManagerIndexerNotAuthorized(address indexer, address allocationId); + error AllocationManagerNotAuthorized(address indexer, address allocationId); /** * @notice Initializes the contract and parent contracts @@ -257,16 +257,16 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * * Emits a {IndexingRewardsCollected} event. * - * @param indexer The address of the indexer + * @param _indexer The address of the indexer * @param _data Encoded data containing: * - address `allocationId`: The id of the allocation to collect rewards for * - bytes32 `poi`: The POI being presented */ - function _collectIndexingRewards(address indexer, bytes memory _data) internal returns (uint256) { + function _collectIndexingRewards(address _indexer, bytes memory _data) internal returns (uint256) { (address allocationId, bytes32 poi) = abi.decode(_data, (address, bytes32)); Allocation.State memory allocation = allocations.get(allocationId); - require(allocation.indexer == indexer, AllocationManagerIndexerNotAuthorized(indexer, allocationId)); + require(allocation.indexer == _indexer, AllocationManagerNotAuthorized(_indexer, allocationId)); require(allocation.isOpen(), AllocationManagerAllocationClosed(allocationId)); // Mint indexing rewards if all conditions are met diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index cf1b20dca..73466c50c 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -42,8 +42,9 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { // Attempt to close other indexer's allocation bytes memory data = abi.encode(allocationID); vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceInvalidIndexer.selector, - newIndexer + ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, + newIndexer, + allocationID )); subgraphService.stopService(newIndexer, data); } diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index 5c4a67834..034af2f9f 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -86,7 +86,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { _approveCollector(tokensPayment128); subgraphService.collect(users.indexer, paymentType, data); - + uint256 indexerBalance = token.balanceOf(users.indexer); uint256 tokensProtocol = tokensPayment128.mulPPM(protocolPaymentCut); uint256 curationTokens = tokensPayment128.mulPPMRoundUp(curationCut); @@ -141,7 +141,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { _createAndStartAllocation(newIndexer, tokens); bytes memory data = _getQueryFeeEncodedData(newIndexer, uint128(tokens)); vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceInvalidAllocationIndexer.selector, + ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, newIndexer, allocationID )); @@ -157,7 +157,8 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { _createAndStartAllocation(newIndexer, tokens); bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceInvalidIndexer.selector, + ISubgraphService.SubgraphServiceIndexerMismatch.selector, + users.indexer, newIndexer )); subgraphService.collect(newIndexer, paymentType, data); @@ -173,7 +174,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { bytes memory data = abi.encode(allocationID, bytes32("POI1")); // Attempt to collect from other indexer's allocation vm.expectRevert(abi.encodeWithSelector( - AllocationManager.AllocationManagerIndexerNotAuthorized.selector, + AllocationManager.AllocationManagerNotAuthorized.selector, newIndexer, allocationID )); From c783118d4305b2ab74ab759383ff9a71e0f245c9 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 14 Aug 2024 16:21:48 -0300 Subject: [PATCH 152/277] fix: resize only open allocations and access control (OZ C-05) --- .../contracts/SubgraphService.sol | 2 +- .../contracts/utilities/AllocationManager.sol | 13 ++- .../test/SubgraphBaseTest.t.sol | 2 +- .../test/mocks/MockRewardsManager.sol | 12 +- .../test/shared/SubgraphServiceShared.t.sol | 17 ++- .../subgraphService/SubgraphService.t.sol | 49 ++++++-- .../subgraphService/allocate/resize.t.sol | 106 ++++++++++++++++++ .../test/subgraphService/allocate/stop.t.sol | 9 +- .../subgraphService/collect/collect.t.sol | 11 +- .../subgraph-service/test/utils/Constants.sol | 1 + 10 files changed, 187 insertions(+), 35 deletions(-) create mode 100644 packages/subgraph-service/test/subgraphService/allocate/resize.t.sol diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 1833515c4..9ae1f18c7 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -299,7 +299,7 @@ contract SubgraphService is onlyRegisteredIndexer(indexer) whenNotPaused { - _resizeAllocation(allocationId, tokens, delegationRatio); + _resizeAllocation(indexer, allocationId, tokens, delegationRatio); } /** diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index bf6165272..800aca723 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -340,20 +340,26 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * These will be paid out when the indexer presents a POI. * * Requirements: + * - `_indexer` must be the owner of the allocation + * - Allocation must be open * - `_tokens` must be different from the current allocation size * * Emits a {AllocationResized} event. * + * @param _indexer The address of the indexer * @param _allocationId The id of the allocation to be resized * @param _tokens The new amount of tokens to allocate * @param _delegationRatio The delegation ratio to consider when locking tokens */ function _resizeAllocation( + address _indexer, address _allocationId, uint256 _tokens, uint32 _delegationRatio ) internal returns (Allocation.State memory) { Allocation.State memory allocation = allocations.get(_allocationId); + require(allocation.indexer == _indexer, AllocationManagerNotAuthorized(_indexer, _allocationId)); + require(allocation.isOpen(), AllocationManagerAllocationClosed(_allocationId)); require(_tokens != allocation.tokens, AllocationManagerAllocationSameSize(_allocationId, _tokens)); // Update provision tracker @@ -378,8 +384,11 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca allocations[_allocationId].accRewardsPending += accRewardsPending; // Update total allocated tokens for the subgraph deployment - // underflow: subgraphAllocatedTokens should at least be oldTokens so it can't underflow - subgraphAllocatedTokens[allocation.subgraphDeploymentId] += (_tokens - oldTokens); + if (_tokens > oldTokens) { + subgraphAllocatedTokens[allocation.subgraphDeploymentId] += (_tokens - oldTokens); + } else { + subgraphAllocatedTokens[allocation.subgraphDeploymentId] -= (oldTokens - _tokens); + } emit AllocationResized(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, _tokens, oldTokens); return allocations[_allocationId]; diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 8344875bf..5e1322de3 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -89,7 +89,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { resetPrank(users.deployer); GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); - rewardsManager = new MockRewardsManager(token, rewardsPerSignal); + rewardsManager = new MockRewardsManager(token, rewardsPerSignal, rewardsPerSubgraphAllocationUpdate); curation = new MockCuration(); // GraphPayments predict address diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index dad236c7a..52ff6a4dc 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -22,12 +22,15 @@ contract MockRewardsManager is IRewardsManager { MockGRTToken public token; uint256 public rewardsPerSignal; + uint256 public rewardsPerSubgraphAllocationUpdate; + mapping(bytes32 => bool) public subgraphs; uint256 private constant FIXED_POINT_SCALING_FACTOR = 1e18; - constructor(MockGRTToken _token, uint256 _rewardsPerSignal) { + constructor(MockGRTToken _token, uint256 _rewardsPerSignal, uint256 _rewardsPerSubgraphAllocationUpdate) { token = _token; rewardsPerSignal = _rewardsPerSignal; + rewardsPerSubgraphAllocationUpdate = _rewardsPerSubgraphAllocationUpdate; } // -- Config -- @@ -83,7 +86,12 @@ contract MockRewardsManager is IRewardsManager { function onSubgraphSignalUpdate(bytes32) external pure returns (uint256) {} - function onSubgraphAllocationUpdate(bytes32) external pure returns (uint256) { + function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) external returns (uint256) { + if (subgraphs[_subgraphDeploymentID]) { + return rewardsPerSubgraphAllocationUpdate; + } + + subgraphs[_subgraphDeploymentID] = true; return 0; } } \ No newline at end of file diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index 3db0509ec..a67a151c1 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -49,11 +49,15 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { */ function _createProvision(uint256 tokens) internal { - token.approve(address(staking), tokens); - staking.stakeTo(users.indexer, tokens); + _stakeTo(users.indexer, tokens); staking.provision(users.indexer, address(subgraphService), tokens, maxSlashingPercentage, disputePeriod); } + function _addToProvision(address _indexer, uint256 _tokens) internal { + _stakeTo(_indexer, _tokens); + staking.addToProvision(_indexer, address(subgraphService), _tokens); + } + function _registerIndexer(address rewardsDestination) internal { subgraphService.register(users.indexer, abi.encode("url", "geoHash", rewardsDestination)); } @@ -65,4 +69,13 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); subgraphService.startService(users.indexer, data); } + + /* + * PRIVATE + */ + + function _stakeTo(address _indexer, uint256 _tokens) internal { + token.approve(address(staking), _tokens); + staking.stakeTo(_indexer, _tokens); + } } diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index f0bc41c58..89b613344 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -3,9 +3,14 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; + import { SubgraphServiceSharedTest } from "../shared/SubgraphServiceShared.t.sol"; contract SubgraphServiceTest is SubgraphServiceSharedTest { + using PPMMath for uint256; /* * VARIABLES @@ -33,20 +38,44 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { * HELPERS */ - function _createAndStartAllocation(address indexer, uint256 tokens) internal { - mint(indexer, tokens); + function _createAndStartAllocation(address _indexer, uint256 _tokens) internal { + mint(_indexer, _tokens); - resetPrank(indexer); - token.approve(address(staking), tokens); - staking.stakeTo(indexer, tokens); - staking.provision(indexer, address(subgraphService), tokens, maxSlashingPercentage, disputePeriod); - subgraphService.register(indexer, abi.encode("url", "geoHash", address(0))); + resetPrank(_indexer); + token.approve(address(staking), _tokens); + staking.stakeTo(_indexer, _tokens); + staking.provision(_indexer, address(subgraphService), _tokens, maxSlashingPercentage, disputePeriod); + subgraphService.register(_indexer, abi.encode("url", "geoHash", address(0))); (address newIndexerAllocationId, uint256 newIndexerAllocationKey) = makeAddrAndKey("newIndexerAllocationId"); - bytes32 digest = subgraphService.encodeAllocationProof(indexer, newIndexerAllocationId); + bytes32 digest = subgraphService.encodeAllocationProof(_indexer, newIndexerAllocationId); (uint8 v, bytes32 r, bytes32 s) = vm.sign(newIndexerAllocationKey, digest); - bytes memory data = abi.encode(subgraphDeployment, tokens, newIndexerAllocationId, abi.encodePacked(r, s, v)); - subgraphService.startService(indexer, data); + bytes memory data = abi.encode(subgraphDeployment, _tokens, newIndexerAllocationId, abi.encodePacked(r, s, v)); + subgraphService.startService(_indexer, data); + } + + function _stopAllocation(address _indexer, address _allocationID) internal { + resetPrank(_indexer); + assertTrue(subgraphService.isActiveAllocation(_allocationID)); + bytes memory data = abi.encode(_allocationID); + vm.expectEmit(address(subgraphService)); + emit IDataService.ServiceStopped(_indexer, data); + subgraphService.stopService(_indexer, data); + + uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); + assertEq(subgraphAllocatedTokens, 0); + } + + function _collectIndexingRewards(address _indexer, address _allocationID, uint256 _tokens) internal { + resetPrank(_indexer); + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory data = abi.encode(_allocationID, bytes32("POI1")); + + uint256 indexerPreviousProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); + subgraphService.collect(_indexer, paymentType, data); + + uint256 indexerProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); + assertEq(indexerProvisionBalance, indexerPreviousProvisionBalance + _tokens.mulPPM(rewardsPerSignal)); } } diff --git a/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol b/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol new file mode 100644 index 000000000..6010a1da7 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { Allocation } from "../../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceAllocateResizeTest is SubgraphServiceTest { + + /* + * Helpers + */ + + function _setupResize(address _indexer, uint256 _tokens) private { + + token.approve(address(staking), _tokens); + staking.stakeTo(_indexer, _tokens); + staking.addToProvision(_indexer, address(subgraphService), _tokens); + } + + function _resizeAllocation(address _indexer, address _allocationID, bytes32 _subgraphDeployment, uint256 _tokens) private { + uint256 oldAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); + vm.expectEmit(address(subgraphService)); + emit AllocationManager.AllocationResized(_indexer, _allocationID, _subgraphDeployment, _tokens, oldAllocatedTokens); + subgraphService.resizeAllocation(_indexer, _allocationID, _tokens); + + Allocation.State memory allocation = subgraphService.getAllocation(_allocationID); + assertEq(allocation.tokens, _tokens); + assertEq(allocation.accRewardsPerAllocatedToken, rewardsPerSubgraphAllocationUpdate); + + uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); + assertEq(subgraphAllocatedTokens, _tokens); + } + + /* + * TESTS + */ + + function testResize_Allocation(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, 1, MAX_TOKENS); + vm.assume(resizeTokens != tokens); + + mint(users.indexer, resizeTokens); + _addToProvision(users.indexer, resizeTokens); + _resizeAllocation(users.indexer, allocationID, subgraphDeployment, resizeTokens); + } + + function testResize_Allocation_AfterCollectingIndexingRewards(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, 1, MAX_TOKENS); + vm.assume(resizeTokens != tokens); + + mint(users.indexer, resizeTokens); + _collectIndexingRewards(users.indexer, allocationID, tokens); + _addToProvision(users.indexer, resizeTokens); + _resizeAllocation(users.indexer, allocationID, subgraphDeployment, resizeTokens); + } + + function testResize_Allocation_SecondTime(uint256 tokens, uint256 firstResizeTokens, uint256 secondResizeTokens) public useIndexer useAllocation(tokens) { + firstResizeTokens = bound(firstResizeTokens, 1, MAX_TOKENS); + secondResizeTokens = bound(secondResizeTokens, 1, MAX_TOKENS); + vm.assume(firstResizeTokens != tokens); + vm.assume(secondResizeTokens != firstResizeTokens); + + mint(users.indexer, firstResizeTokens); + _addToProvision(users.indexer, firstResizeTokens); + _resizeAllocation(users.indexer, allocationID, subgraphDeployment, firstResizeTokens); + + mint(users.indexer, secondResizeTokens); + _addToProvision(users.indexer, secondResizeTokens); + _resizeAllocation(users.indexer, allocationID, subgraphDeployment, secondResizeTokens); + } + + function testResize_RevertWhen_NotAuthorized(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, tokens + 1, MAX_TOKENS); + + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerNotAuthorized.selector, + newIndexer, + allocationID + )); + subgraphService.resizeAllocation(newIndexer, allocationID, resizeTokens); + } + + function testResize_RevertWhen_SameSize(uint256 tokens) public useIndexer useAllocation(tokens) { + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerAllocationSameSize.selector, + allocationID, + tokens + )); + subgraphService.resizeAllocation(users.indexer, allocationID, tokens); + } + + function testResize_RevertIf_AllocationIsClosed(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, tokens + 1, MAX_TOKENS); + _stopAllocation(users.indexer, allocationID); + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerAllocationClosed.selector, + allocationID + )); + subgraphService.resizeAllocation(users.indexer, allocationID, resizeTokens); + } +} diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index 73466c50c..6e53ab886 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -24,14 +24,7 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { */ function testStop_Allocation(uint256 tokens) public useIndexer useAllocation(tokens) { - assertTrue(subgraphService.isActiveAllocation(allocationID)); - bytes memory data = abi.encode(allocationID); - vm.expectEmit(address(subgraphService)); - emit IDataService.ServiceStopped(users.indexer, data); - subgraphService.stopService(users.indexer, data); - - uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); - assertEq(subgraphAllocatedTokens, 0); + _stopAllocation(users.indexer, allocationID); } function testStop_RevertWhen_IndexerIsNotTheAllocationOwner(uint256 tokens) public useIndexer useAllocation(tokens) { diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index 034af2f9f..b9f2fbcd1 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -96,15 +96,8 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { assertEq(indexerBalance, indexerPreviousBalance + expectedIndexerTokensPayment); } - function testCollect_IndexingFees(uint256 tokens) public useIndexer useAllocation(tokens) { - IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; - bytes memory data = abi.encode(allocationID, bytes32("POI1")); - - uint256 indexerPreviousProvisionBalance = staking.getProviderTokensAvailable(users.indexer, address(subgraphService)); - subgraphService.collect(users.indexer, paymentType, data); - - uint256 indexerProvisionBalance = staking.getProviderTokensAvailable(users.indexer, address(subgraphService)); - assertEq(indexerProvisionBalance, indexerPreviousProvisionBalance + tokens.mulPPM(rewardsPerSignal)); + function testCollect_IndexingRewards(uint256 tokens) public useIndexer useAllocation(tokens) { + _collectIndexingRewards(users.indexer, allocationID, tokens); } function testCollect_RevertWhen_InvalidPayment( diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index 75ff738a8..e35659062 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -25,4 +25,5 @@ abstract contract Constants { uint256 internal constant protocolPaymentCut = 10000; // RewardsMananger parameters uint256 public constant rewardsPerSignal = 10000; + uint256 public constant rewardsPerSubgraphAllocationUpdate = 1000; } \ No newline at end of file From 787604656e76c33040000283d4491f86b3127f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 15 Aug 2024 13:32:25 -0300 Subject: [PATCH 153/277] fix: change pending rewards due to resize to token amounts instead of per token (OZ-H01) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/rewards/IRewardsIssuer.sol | 9 ++++- .../contracts/rewards/IRewardsManager.sol | 2 + .../contracts/rewards/RewardsManager.sol | 33 ++++++++++++--- .../contracts/staking/IStakingBase.sol | 4 +- .../contracts/contracts/staking/Staking.sol | 4 +- packages/contracts/package.json | 2 +- .../staking/HorizonStakingExtension.sol | 5 ++- .../test/data-service/DataService.t.sol | 16 ++++---- .../test/staking/allocation/allocation.t.sol | 3 +- .../contracts/SubgraphService.sol | 19 +++++++-- .../contracts/libraries/Allocation.sol | 3 +- .../contracts/utilities/AllocationManager.sol | 7 +++- .../test/mocks/MockRewardsManager.sol | 2 + .../subgraphService/allocate/resize.t.sol | 40 ++++++++++++++----- yarn.lock | 4 +- 15 files changed, 113 insertions(+), 40 deletions(-) diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol index 949c564a2..a5400a6cf 100644 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -10,13 +10,20 @@ interface IRewardsIssuer { * @return subgraphDeploymentId Subgraph deployment id for the allocation * @return tokens Amount of allocated tokens * @return accRewardsPerAllocatedToken Rewards snapshot + * @return accRewardsPending Tokens pending to be claimed */ function getAllocationData( address allocationId ) external view - returns (address indexer, bytes32 subgraphDeploymentId, uint256 tokens, uint256 accRewardsPerAllocatedToken); + returns ( + address indexer, + bytes32 subgraphDeploymentId, + uint256 tokens, + uint256 accRewardsPerAllocatedToken, + uint256 accRewardsPending + ); /** * @notice Return the total amount of tokens allocated to subgraph. diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index e511748e3..4030ad2e5 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -43,6 +43,8 @@ interface IRewardsManager { function getRewards(address _allocationID) external view returns (uint256); + function calcRewards(uint256 _tokens, uint256 _accRewardsPerAllocatedToken) external pure returns (uint256); + // -- Updates -- function updateAccRewardsPerSignal() external returns (uint256); diff --git a/packages/contracts/contracts/rewards/RewardsManager.sol b/packages/contracts/contracts/rewards/RewardsManager.sol index 21512ec80..a9b3b61e2 100644 --- a/packages/contracts/contracts/rewards/RewardsManager.sol +++ b/packages/contracts/contracts/rewards/RewardsManager.sol @@ -357,12 +357,30 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa return 0; } - (, bytes32 subgraphDeploymentId, uint256 tokens, uint256 alloAccRewardsPerAllocatedToken) = IRewardsIssuer( - rewardsIssuer - ).getAllocationData(_allocationID); + ( + , + bytes32 subgraphDeploymentId, + uint256 tokens, + uint256 alloAccRewardsPerAllocatedToken, + uint256 accRewardsPending + ) = IRewardsIssuer(rewardsIssuer).getAllocationData(_allocationID); (uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken(subgraphDeploymentId); - return _calcRewards(tokens, alloAccRewardsPerAllocatedToken, accRewardsPerAllocatedToken); + return + accRewardsPending.add(_calcRewards(tokens, alloAccRewardsPerAllocatedToken, accRewardsPerAllocatedToken)); + } + + /** + * @dev Calculate rewards for a given accumulated rewards per allocated token. + * @param _tokens Tokens allocated + * @param _accRewardsPerAllocatedToken Allocation accumulated rewards per token + * @return Rewards amount + */ + function calcRewards( + uint256 _tokens, + uint256 _accRewardsPerAllocatedToken + ) external pure override returns (uint256) { + return _accRewardsPerAllocatedToken.mul(_tokens).div(FIXED_POINT_SCALING_FACTOR); } /** @@ -400,7 +418,8 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa address indexer, bytes32 subgraphDeploymentID, uint256 tokens, - uint256 accRewardsPerAllocatedToken + uint256 accRewardsPerAllocatedToken, + uint256 accRewardsPending ) = IRewardsIssuer(rewardsIssuer).getAllocationData(_allocationID); uint256 updatedAccRewardsPerAllocatedToken = onSubgraphAllocationUpdate(subgraphDeploymentID); @@ -412,7 +431,9 @@ contract RewardsManager is RewardsManagerV5Storage, GraphUpgradeable, IRewardsMa } // Calculate rewards accrued by this allocation - uint256 rewards = _calcRewards(tokens, accRewardsPerAllocatedToken, updatedAccRewardsPerAllocatedToken); + uint256 rewards = accRewardsPending.add( + _calcRewards(tokens, accRewardsPerAllocatedToken, updatedAccRewardsPerAllocatedToken) + ); if (rewards > 0) { // Mint directly to rewards issuer for the reward amount // The rewards issuer contract will do bookkeeping of the reward and diff --git a/packages/contracts/contracts/staking/IStakingBase.sol b/packages/contracts/contracts/staking/IStakingBase.sol index 6ca3957f4..f01ca4326 100644 --- a/packages/contracts/contracts/staking/IStakingBase.sol +++ b/packages/contracts/contracts/staking/IStakingBase.sol @@ -366,7 +366,9 @@ interface IStakingBase is IStakingData { * @dev Note that this is only to make tests pass, as the staking contract with * this changes will never get deployed. HorizonStaking is taking it's place. */ - function getAllocationData(address _allocationID) external view returns (address, bytes32, uint256, uint256); + function getAllocationData( + address _allocationID + ) external view returns (address, bytes32, uint256, uint256, uint256); /** * @dev New function to get the allocation active status for the rewards manager diff --git a/packages/contracts/contracts/staking/Staking.sol b/packages/contracts/contracts/staking/Staking.sol index 83745c30a..d44d4767e 100644 --- a/packages/contracts/contracts/staking/Staking.sol +++ b/packages/contracts/contracts/staking/Staking.sol @@ -479,9 +479,9 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M */ function getAllocationData( address _allocationID - ) external view override returns (address, bytes32, uint256, uint256) { + ) external view override returns (address, bytes32, uint256, uint256, uint256) { Allocation memory alloc = __allocations[_allocationID]; - return (alloc.indexer, alloc.subgraphDeploymentID, alloc.tokens, alloc.accRewardsPerAllocatedToken); + return (alloc.indexer, alloc.subgraphDeploymentID, alloc.tokens, alloc.accRewardsPerAllocatedToken, 0); } /** diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 85f02990d..b6cb22e0c 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -19,7 +19,7 @@ }, "devDependencies": { "@arbitrum/sdk": "~3.1.13", - "@defi-wonderland/smock": "^2.0.7", + "@defi-wonderland/smock": "^2.4.0", "@ethersproject/experimental": "^5.6.0", "@graphprotocol/common-ts": "^1.8.3", "@nomiclabs/hardhat-ethers": "^2.2.3", diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 9667d35bb..3aa425154 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -238,14 +238,15 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon * @notice Return allocation data by ID. * @dev To be called by the Rewards Manager to calculate rewards issuance. * @dev TODO: Remove after Horizon transition period + * @dev Note that the accRewardsPending field is not used and will always be zero. * @param allocationID Address used as allocation identifier * @return Allocation data */ function getAllocationData( address allocationID - ) external view override returns (address, bytes32, uint256, uint256) { + ) external view override returns (address, bytes32, uint256, uint256, uint256) { Allocation memory allo = __DEPRECATED_allocations[allocationID]; - return (allo.indexer, allo.subgraphDeploymentID, allo.tokens, allo.accRewardsPerAllocatedToken); + return (allo.indexer, allo.subgraphDeploymentID, allo.tokens, allo.accRewardsPerAllocatedToken, 0); } /** diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol index ecba7ae52..ea5fd51a7 100644 --- a/packages/horizon/test/data-service/DataService.t.sol +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -254,13 +254,15 @@ contract DataServiceTest is HorizonStakingSharedTest { staking.setProvisionParameters(users.indexer, address(dataService), maxVerifierCut, thawingPeriod); // accept provision parameters - vm.expectEmit(); - emit IHorizonStakingMain.ProvisionParametersSet( - users.indexer, - address(dataService), - maxVerifierCut, - thawingPeriod - ); + if (maxVerifierCut != dataService.VERIFIER_CUT_MIN() || thawingPeriod != dataService.THAWING_PERIOD_MIN()) { + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersSet( + users.indexer, + address(dataService), + maxVerifierCut, + thawingPeriod + ); + } dataService.acceptProvisionParameters(users.indexer); } diff --git a/packages/horizon/test/staking/allocation/allocation.t.sol b/packages/horizon/test/staking/allocation/allocation.t.sol index feb89ec7c..83e23a81f 100644 --- a/packages/horizon/test/staking/allocation/allocation.t.sol +++ b/packages/horizon/test/staking/allocation/allocation.t.sol @@ -26,12 +26,13 @@ contract HorizonStakingAllocationTest is HorizonStakingExtensionTest { } function testAllocation_GetAllocationData() public useAllocation { - (address indexer, bytes32 subgraphDeploymentID, uint256 tokens, uint256 accRewardsPerAllocatedToken) = + (address indexer, bytes32 subgraphDeploymentID, uint256 tokens, uint256 accRewardsPerAllocatedToken, uint256 accRewardsPending) = staking.getAllocationData(_allocationId); assertEq(indexer, _allocation.indexer); assertEq(subgraphDeploymentID, _allocation.subgraphDeploymentID); assertEq(tokens, _allocation.tokens); assertEq(accRewardsPerAllocatedToken, _allocation.accRewardsPerAllocatedToken); + assertEq(accRewardsPending, 0); } function testAllocation_GetAllocationState_Active() public useAllocation { diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 9ae1f18c7..a3b9d1541 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -221,7 +221,10 @@ contract SubgraphService is bytes calldata data ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { address allocationId = abi.decode(data, (address)); - require(allocations[allocationId].indexer == indexer, SubgraphServiceAllocationNotAuthorized(indexer, allocationId)); + require( + allocations[allocationId].indexer == indexer, + SubgraphServiceAllocationNotAuthorized(indexer, allocationId) + ); _closeAllocation(allocationId); emit ServiceStopped(indexer, data); } @@ -251,7 +254,14 @@ contract SubgraphService is address indexer, IGraphPayments.PaymentTypes paymentType, bytes calldata data - ) external override onlyProvisionAuthorized(indexer) onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + ) + external + override + onlyProvisionAuthorized(indexer) + onlyValidProvision(indexer) + onlyRegisteredIndexer(indexer) + whenNotPaused + { uint256 paymentCollected = 0; if (paymentType == IGraphPayments.PaymentTypes.QueryFee) { @@ -391,13 +401,14 @@ contract SubgraphService is */ function getAllocationData( address allocationId - ) external view override returns (address, bytes32, uint256, uint256) { + ) external view override returns (address, bytes32, uint256, uint256, uint256) { Allocation.State memory allo = allocations[allocationId]; return ( allo.indexer, allo.subgraphDeploymentId, allo.tokens, - allo.accRewardsPerAllocatedToken + allo.accRewardsPending + allo.accRewardsPerAllocatedToken, + allo.accRewardsPending ); } diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index 0df8f6e21..7511f360a 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -26,8 +26,7 @@ library Allocation { uint256 lastPOIPresentedAt; // Accumulated rewards per allocated token uint256 accRewardsPerAllocatedToken; - // Accumulated rewards per allocated token that are pending to be claimed - // due to an allocation resize + // Accumulated rewards that are pending to be claimed due allocation resize uint256 accRewardsPending; } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 800aca723..1ddb25f5e 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -374,14 +374,17 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca uint256 accRewardsPerAllocatedToken = _graphRewardsManager().onSubgraphAllocationUpdate( allocation.subgraphDeploymentId ); - uint256 accRewardsPending = !allocation.isAltruistic() + uint256 accRewardsPerAllocatedTokenPending = !allocation.isAltruistic() ? accRewardsPerAllocatedToken - allocation.accRewardsPerAllocatedToken : 0; // Update the allocation allocations[_allocationId].tokens = _tokens; allocations[_allocationId].accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; - allocations[_allocationId].accRewardsPending += accRewardsPending; + allocations[_allocationId].accRewardsPending += _graphRewardsManager().calcRewards( + oldTokens, + accRewardsPerAllocatedTokenPending + ); // Update total allocated tokens for the subgraph deployment if (_tokens > oldTokens) { diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index 52ff6a4dc..59ca5577e 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -63,6 +63,8 @@ contract MockRewardsManager is IRewardsManager { function getRewards(address) external view returns (uint256) {} + function calcRewards(uint256, uint256) external pure returns (uint256) {} + // -- Updates -- function updateAccRewardsPerSignal() external returns (uint256) {} diff --git a/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol b/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol index 6010a1da7..9fdd327dc 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol @@ -14,24 +14,46 @@ contract SubgraphServiceAllocateResizeTest is SubgraphServiceTest { */ function _setupResize(address _indexer, uint256 _tokens) private { - token.approve(address(staking), _tokens); staking.stakeTo(_indexer, _tokens); staking.addToProvision(_indexer, address(subgraphService), _tokens); } function _resizeAllocation(address _indexer, address _allocationID, bytes32 _subgraphDeployment, uint256 _tokens) private { - uint256 oldAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); + // before + uint256 beforeSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); + uint256 beforeAllocatedTokens = subgraphService.allocationProvisionTracker(_indexer); + Allocation.State memory beforeAllocation = subgraphService.getAllocation(_allocationID); + + uint256 allocatedTokensDelta; + if (_tokens > beforeAllocation.tokens) { + allocatedTokensDelta = _tokens - beforeAllocation.tokens; + } else { + allocatedTokensDelta = beforeAllocation.tokens - _tokens; + } + + // resize vm.expectEmit(address(subgraphService)); - emit AllocationManager.AllocationResized(_indexer, _allocationID, _subgraphDeployment, _tokens, oldAllocatedTokens); + emit AllocationManager.AllocationResized(_indexer, _allocationID, _subgraphDeployment, _tokens, beforeSubgraphAllocatedTokens); subgraphService.resizeAllocation(_indexer, _allocationID, _tokens); - Allocation.State memory allocation = subgraphService.getAllocation(_allocationID); - assertEq(allocation.tokens, _tokens); - assertEq(allocation.accRewardsPerAllocatedToken, rewardsPerSubgraphAllocationUpdate); - - uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); - assertEq(subgraphAllocatedTokens, _tokens); + // after + uint256 afterSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); + uint256 afterAllocatedTokens = subgraphService.allocationProvisionTracker(_indexer); + Allocation.State memory afterAllocation = subgraphService.getAllocation(_allocationID); + uint256 accRewardsPerAllocatedTokenDelta = afterAllocation.accRewardsPerAllocatedToken - beforeAllocation.accRewardsPerAllocatedToken; + uint256 afterAccRewardsPending = rewardsManager.calcRewards(beforeAllocation.tokens, accRewardsPerAllocatedTokenDelta); + + //assert + if (_tokens > beforeAllocation.tokens) { + assertEq(afterAllocatedTokens, beforeAllocatedTokens + allocatedTokensDelta); + } else { + assertEq(afterAllocatedTokens, beforeAllocatedTokens - allocatedTokensDelta); + } + assertEq(afterAllocation.tokens, _tokens); + assertEq(afterAllocation.accRewardsPerAllocatedToken, rewardsPerSubgraphAllocationUpdate); + assertEq(afterAllocation.accRewardsPending, afterAccRewardsPending); + assertEq(afterSubgraphAllocatedTokens, _tokens); } /* diff --git a/yarn.lock b/yarn.lock index 29b385618..4088ee33e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1469,7 +1469,7 @@ __metadata: languageName: node linkType: hard -"@defi-wonderland/smock@npm:^2.0.7": +"@defi-wonderland/smock@npm:^2.4.0": version: 2.4.0 resolution: "@defi-wonderland/smock@npm:2.4.0" dependencies: @@ -2802,7 +2802,7 @@ __metadata: resolution: "@graphprotocol/contracts@workspace:packages/contracts" dependencies: "@arbitrum/sdk": "npm:~3.1.13" - "@defi-wonderland/smock": "npm:^2.0.7" + "@defi-wonderland/smock": "npm:^2.4.0" "@ethersproject/experimental": "npm:^5.6.0" "@graphprotocol/common-ts": "npm:^1.8.3" "@graphprotocol/sdk": "workspace:^0.5.0" From 7726b5888db40288a6ff3acd49032ed90b276aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 15 Aug 2024 14:27:25 -0300 Subject: [PATCH 154/277] fix: pin smock version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/contracts/eslint.config.js | 2 + packages/contracts/package.json | 2 +- .../test/unit/lib/graphTokenTests.ts | 2 +- yarn.lock | 192 +++++++++++++++++- 4 files changed, 187 insertions(+), 11 deletions(-) diff --git a/packages/contracts/eslint.config.js b/packages/contracts/eslint.config.js index c7c0ba1b2..566196117 100644 --- a/packages/contracts/eslint.config.js +++ b/packages/contracts/eslint.config.js @@ -9,6 +9,8 @@ module.exports = [ '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/no-redundant-type-constituents': 'off', }, }, { diff --git a/packages/contracts/package.json b/packages/contracts/package.json index b6cb22e0c..f4ecce85a 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -19,7 +19,7 @@ }, "devDependencies": { "@arbitrum/sdk": "~3.1.13", - "@defi-wonderland/smock": "^2.4.0", + "@defi-wonderland/smock": "~2.3.0", "@ethersproject/experimental": "^5.6.0", "@graphprotocol/common-ts": "^1.8.3", "@nomiclabs/hardhat-ethers": "^2.2.3", diff --git a/packages/contracts/test/unit/lib/graphTokenTests.ts b/packages/contracts/test/unit/lib/graphTokenTests.ts index 77682ada9..299458080 100644 --- a/packages/contracts/test/unit/lib/graphTokenTests.ts +++ b/packages/contracts/test/unit/lib/graphTokenTests.ts @@ -55,7 +55,7 @@ export function grtTests(isL2: boolean): void { return permit } - async function createPermitTransaction(permit: Permit, signer: string, salt: string) { + function createPermitTransaction(permit: Permit, signer: string, salt: string) { const signature: Signature = signPermit(signer, graph.chainId, grt.address, permit, salt) const wallet = new ethers.Wallet(signer, graph.provider) return grt diff --git a/yarn.lock b/yarn.lock index 4088ee33e..4d5746433 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1469,11 +1469,13 @@ __metadata: languageName: node linkType: hard -"@defi-wonderland/smock@npm:^2.4.0": - version: 2.4.0 - resolution: "@defi-wonderland/smock@npm:2.4.0" +"@defi-wonderland/smock@npm:~2.3.0": + version: 2.3.5 + resolution: "@defi-wonderland/smock@npm:2.3.5" dependencies: - "@nomicfoundation/ethereumjs-util": "npm:^9.0.4" + "@nomicfoundation/ethereumjs-evm": "npm:^1.0.0-rc.3" + "@nomicfoundation/ethereumjs-util": "npm:^8.0.0-rc.3" + "@nomicfoundation/ethereumjs-vm": "npm:^6.0.0-rc.3" diff: "npm:^5.0.0" lodash.isequal: "npm:^4.5.0" lodash.isequalwith: "npm:^4.4.0" @@ -1485,8 +1487,8 @@ __metadata: "@ethersproject/abstract-signer": ^5 "@nomiclabs/hardhat-ethers": ^2 ethers: ^5 - hardhat: ^2.21.0 - checksum: 166dfb4b9e00c29466f0cf27dc2009e8139f9e6a31e42b74d55f5e6ac690d5f7137ae5acf1b8ff846ae46915608f6de921f2bef47a485088e57d951cac72b054 + hardhat: ^2 + checksum: c831563fe6607841d69f5936011398a492f760f52f9cb17626b2949ff3ef7668729acc4a3a944f739417b2d1b99bc6c83580f236189f27431224021c66ac1821 languageName: node linkType: hard @@ -2802,7 +2804,7 @@ __metadata: resolution: "@graphprotocol/contracts@workspace:packages/contracts" dependencies: "@arbitrum/sdk": "npm:~3.1.13" - "@defi-wonderland/smock": "npm:^2.4.0" + "@defi-wonderland/smock": "npm:~2.3.0" "@ethersproject/experimental": "npm:^5.6.0" "@graphprotocol/common-ts": "npm:^1.8.3" "@graphprotocol/sdk": "workspace:^0.5.0" @@ -4251,6 +4253,20 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-block@npm:4.2.2": + version: 4.2.2 + resolution: "@nomicfoundation/ethereumjs-block@npm:4.2.2" + dependencies: + "@nomicfoundation/ethereumjs-common": "npm:3.1.2" + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" + "@nomicfoundation/ethereumjs-tx": "npm:4.1.2" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + ethereum-cryptography: "npm:0.1.3" + checksum: 1c211294b3064d2bbfcf33b460438f01fb9cd77429314a90a5e2ffce5162019a384f4ae7d3825cfd386a140db191b251b475427562c53f85beffc786156f817e + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-block@npm:5.0.1": version: 5.0.1 resolution: "@nomicfoundation/ethereumjs-block@npm:5.0.1" @@ -4266,6 +4282,26 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-blockchain@npm:6.2.2": + version: 6.2.2 + resolution: "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2" + dependencies: + "@nomicfoundation/ethereumjs-block": "npm:4.2.2" + "@nomicfoundation/ethereumjs-common": "npm:3.1.2" + "@nomicfoundation/ethereumjs-ethash": "npm:2.0.5" + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + abstract-level: "npm:^1.0.3" + debug: "npm:^4.3.3" + ethereum-cryptography: "npm:0.1.3" + level: "npm:^8.0.0" + lru-cache: "npm:^5.1.1" + memory-level: "npm:^1.0.0" + checksum: 6fe6e315900e1d6a29d59be41f566bdfd5ffdf82ab0fe081b1999dcc4eec3a248ab080d359a56e8cde4e473ca90349b0c50fa1ab707aa3e275fb1c478237e5e2 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-blockchain@npm:7.0.1": version: 7.0.1 resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.1" @@ -4287,6 +4323,16 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-common@npm:3.1.2": + version: 3.1.2 + resolution: "@nomicfoundation/ethereumjs-common@npm:3.1.2" + dependencies: + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + crc-32: "npm:^1.2.0" + checksum: 90910630025b5bb503f36125c45395cc9f875ffdd8137a83e9c1d566678edcc8db40f8ce1dff9da1ef2c91c7d6b6d1fa75c41a9579a5d3a8f0ae669fcea244b1 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-common@npm:4.0.1": version: 4.0.1 resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.1" @@ -4306,6 +4352,20 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-ethash@npm:2.0.5": + version: 2.0.5 + resolution: "@nomicfoundation/ethereumjs-ethash@npm:2.0.5" + dependencies: + "@nomicfoundation/ethereumjs-block": "npm:4.2.2" + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + abstract-level: "npm:^1.0.3" + bigint-crypto-utils: "npm:^3.0.23" + ethereum-cryptography: "npm:0.1.3" + checksum: 7a90ef53ae4c1ac5a314c3447966fdbefcc96481ae3a05d59e881053350c55be7c841708c61c79a2af40bbb0181d6e0db42601592f17a4db1611b199d49e8544 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-ethash@npm:3.0.1": version: 3.0.1 resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.1" @@ -4320,6 +4380,22 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-evm@npm:1.3.2, @nomicfoundation/ethereumjs-evm@npm:^1.0.0-rc.3": + version: 1.3.2 + resolution: "@nomicfoundation/ethereumjs-evm@npm:1.3.2" + dependencies: + "@nomicfoundation/ethereumjs-common": "npm:3.1.2" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + "@types/async-eventemitter": "npm:^0.2.1" + async-eventemitter: "npm:^0.2.4" + debug: "npm:^4.3.3" + ethereum-cryptography: "npm:0.1.3" + mcl-wasm: "npm:^0.7.1" + rustbn.js: "npm:~0.2.0" + checksum: 4aa14d7dce597a91c25bec5975022348741cebf6ed20cda028ddcbebe739ba2e6f4c879fa1ebe849bd5c78d3fd2443ebbb7d57e1fca5a98fbe88fc9ce15d9fd6 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-evm@npm:2.0.1": version: 2.0.1 resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.1" @@ -4336,6 +4412,15 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-rlp@npm:4.0.3": + version: 4.0.3 + resolution: "@nomicfoundation/ethereumjs-rlp@npm:4.0.3" + bin: + rlp: bin/rlp + checksum: 3e3c07abf53ff5832afbbdf3f3687e11e2e829699348eea1ae465084c72e024559d97e351e8f0fb27f32c7896633c7dd50b19d8de486e89cde777fd5447381cd + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-rlp@npm:5.0.1": version: 5.0.1 resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.1" @@ -4354,6 +4439,21 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-statemanager@npm:1.0.5": + version: 1.0.5 + resolution: "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5" + dependencies: + "@nomicfoundation/ethereumjs-common": "npm:3.1.2" + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + debug: "npm:^4.3.3" + ethereum-cryptography: "npm:0.1.3" + functional-red-black-tree: "npm:^1.0.1" + checksum: 4a05b7a86a1bbc8fd409416edf437d99d9d4498c438e086c30250cb3dc92ff00086f9ff959f469c72d46178e831104dc15f10465e27fbbf0ca97da27d6889a0c + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-statemanager@npm:2.0.1": version: 2.0.1 resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.1" @@ -4368,6 +4468,18 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-trie@npm:5.0.5": + version: 5.0.5 + resolution: "@nomicfoundation/ethereumjs-trie@npm:5.0.5" + dependencies: + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + ethereum-cryptography: "npm:0.1.3" + readable-stream: "npm:^3.6.0" + checksum: cab544fef4bcdc3acef1bfb4ee9f2fde44b66a22b2329bfd67515facdf115a318961f8bc0e38befded838e8fc513974f90f340b53a98b8469e54960b15cd857a + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-trie@npm:6.0.1": version: 6.0.1 resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.1" @@ -4381,6 +4493,18 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-tx@npm:4.1.2": + version: 4.1.2 + resolution: "@nomicfoundation/ethereumjs-tx@npm:4.1.2" + dependencies: + "@nomicfoundation/ethereumjs-common": "npm:3.1.2" + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + ethereum-cryptography: "npm:0.1.3" + checksum: cb569c882d3ce922acff1a4238864f11109ac5a30dfa481b1ed9c7043c2b773f3a5fc88a3f4fefb62b11c448305296533f555f93d1d969a5abd3c2a13c80ed74 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-tx@npm:5.0.1": version: 5.0.1 resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.1" @@ -4412,6 +4536,16 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-util@npm:8.0.6, @nomicfoundation/ethereumjs-util@npm:^8.0.0-rc.3": + version: 8.0.6 + resolution: "@nomicfoundation/ethereumjs-util@npm:8.0.6" + dependencies: + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + ethereum-cryptography: "npm:0.1.3" + checksum: 647006f4dfa962f61cec54c34ff9939468042cf762ff3b2cf80c8362558f21750348a3cda63dc9890b1cb2ba664f97dc4a892afca5f5d6f95b3ba4d56be5a33b + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-util@npm:9.0.1": version: 9.0.1 resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.1" @@ -4423,7 +4557,7 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-util@npm:9.0.4, @nomicfoundation/ethereumjs-util@npm:^9.0.4": +"@nomicfoundation/ethereumjs-util@npm:9.0.4": version: 9.0.4 resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" dependencies: @@ -4459,6 +4593,30 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-vm@npm:^6.0.0-rc.3": + version: 6.4.2 + resolution: "@nomicfoundation/ethereumjs-vm@npm:6.4.2" + dependencies: + "@nomicfoundation/ethereumjs-block": "npm:4.2.2" + "@nomicfoundation/ethereumjs-blockchain": "npm:6.2.2" + "@nomicfoundation/ethereumjs-common": "npm:3.1.2" + "@nomicfoundation/ethereumjs-evm": "npm:1.3.2" + "@nomicfoundation/ethereumjs-rlp": "npm:4.0.3" + "@nomicfoundation/ethereumjs-statemanager": "npm:1.0.5" + "@nomicfoundation/ethereumjs-trie": "npm:5.0.5" + "@nomicfoundation/ethereumjs-tx": "npm:4.1.2" + "@nomicfoundation/ethereumjs-util": "npm:8.0.6" + "@types/async-eventemitter": "npm:^0.2.1" + async-eventemitter: "npm:^0.2.4" + debug: "npm:^4.3.3" + ethereum-cryptography: "npm:0.1.3" + functional-red-black-tree: "npm:^1.0.1" + mcl-wasm: "npm:^0.7.1" + rustbn.js: "npm:~0.2.0" + checksum: 78e4b0ba20e8fa4ef112bae88f432746647ed48b41918b34855fe08269be3aaff84f95c08b6c61475fb70f24a28ba73612bd2bcd19b3c007c8bf9e11a43fa8e0 + languageName: node + linkType: hard + "@nomicfoundation/hardhat-chai-matchers@npm:^2.0.0": version: 2.0.6 resolution: "@nomicfoundation/hardhat-chai-matchers@npm:2.0.6" @@ -5537,6 +5695,15 @@ __metadata: languageName: node linkType: hard +"@types/async-eventemitter@npm:^0.2.1": + version: 0.2.4 + resolution: "@types/async-eventemitter@npm:0.2.4" + dependencies: + "@types/events": "npm:*" + checksum: 2ae267eb3e959fe5aaf6d850ab06ac2e5b44f1a7e3e421250f3ebaa8a108f641e9050d042980bc35aab98d6fa5f1a62a43cfb7f377011ce9013ed62229327111 + languageName: node + linkType: hard + "@types/bn.js@npm:*, @types/bn.js@npm:^5.1.0, @types/bn.js@npm:^5.1.1": version: 5.1.5 resolution: "@types/bn.js@npm:5.1.5" @@ -5646,6 +5813,13 @@ __metadata: languageName: node linkType: hard +"@types/events@npm:*": + version: 3.0.3 + resolution: "@types/events@npm:3.0.3" + checksum: 3a56f8c51eb4ebc0d05dcadca0c6636c816acc10216ce36c976fad11e54a01f4bb979a07211355686015884753b37f17d74bfdc7aaf4ebb027c1e8a501c7b21d + languageName: node + linkType: hard + "@types/form-data@npm:0.0.33": version: 0.0.33 resolution: "@types/form-data@npm:0.0.33" @@ -7085,7 +7259,7 @@ __metadata: languageName: node linkType: hard -"async-eventemitter@npm:^0.2.2": +"async-eventemitter@npm:^0.2.2, async-eventemitter@npm:^0.2.4": version: 0.2.4 resolution: "async-eventemitter@npm:0.2.4" dependencies: From d80a02523cb64e5b1799897cd3cf156ac069195f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 19 Aug 2024 15:10:24 -0300 Subject: [PATCH 155/277] fix: ensure maxVerifierCut is a valid PPM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../data-service/utilities/ProvisionManager.sol | 4 +++- .../utilities/ProvisionManagerStorage.sol | 4 ++-- packages/horizon/test/data-service/DataService.t.sol | 11 ++++++++++- .../test/data-service/DataServiceUpgradeable.t.sol | 4 +++- .../extensions/DataServicePausableUpgradeable.t.sol | 4 +++- .../subgraph-service/contracts/SubgraphService.sol | 4 ++-- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index de3580aea..c89e9e473 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; import { UintRange } from "../../libraries/UintRange.sol"; +import { PPMMath } from "../../libraries/PPMMath.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { GraphDirectory } from "../../utilities/GraphDirectory.sol"; @@ -150,7 +151,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa // solhint-disable-next-line func-name-mixedcase function __ProvisionManager_init_unchained() internal onlyInitializing { _setProvisionTokensRange(type(uint256).min, type(uint256).max); - _setVerifierCutRange(type(uint32).min, type(uint32).max); + _setVerifierCutRange(type(uint32).min, uint32(PPMMath.MAX_PPM)); _setThawingPeriodRange(type(uint64).min, type(uint64).max); } @@ -197,6 +198,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa */ function _setVerifierCutRange(uint32 _min, uint32 _max) internal { require(_min <= _max, ProvisionManagerInvalidRange(_min, _max)); + require(_max <= PPMMath.MAX_PPM, ProvisionManagerInvalidRange(_min, _max)); minimumVerifierCut = _min; maximumVerifierCut = _max; emit VerifierCutRangeSet(_min, _max); diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index 70f10d6e3..8649055db 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -17,10 +17,10 @@ abstract contract ProvisionManagerV1Storage { /// @notice The maximum thawing period allowed to register a provision in the data service uint64 public maximumThawingPeriod; - /// @notice The minimum verifier cut required to register a provision in the data service + /// @notice The minimum verifier cut required to register a provision in the data service (in PPM) uint32 public minimumVerifierCut; - /// @notice The maximum verifier cut allowed to register a provision in the data service + /// @notice The maximum verifier cut allowed to register a provision in the data service (in PPM) uint32 public maximumVerifierCut; /// @notice How much delegation the service provider can effectively use diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol index ea5fd51a7..98f7aadb3 100644 --- a/packages/horizon/test/data-service/DataService.t.sol +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -22,7 +22,7 @@ contract DataServiceTest is HorizonStakingSharedTest { function test_Constructor_WhenTheContractIsDeployedWithAValidController() external view { _assert_delegationRatio(type(uint32).min); _assert_provisionTokens_range(type(uint256).min, type(uint256).max); - _assert_verifierCut_range(type(uint32).min, type(uint32).max); + _assert_verifierCut_range(type(uint32).min, uint32(PPMMath.MAX_PPM)); _assert_thawingPeriod_range(type(uint64).min, type(uint64).max); } @@ -106,6 +106,7 @@ contract DataServiceTest is HorizonStakingSharedTest { function test_VerifierCut_WhenSettingAValidRange(uint32 min, uint32 max) external { vm.assume(min <= max); + vm.assume(max <= uint32(PPMMath.MAX_PPM)); _assert_set_verifierCut_range(min, max); } @@ -116,6 +117,14 @@ contract DataServiceTest is HorizonStakingSharedTest { dataService.setVerifierCutRange(min, max); } + function test_VerifierCut_RevertWhen_SettingAnInvalidMax(uint32 min, uint32 max) external { + vm.assume(max > uint32(PPMMath.MAX_PPM)); + vm.assume(min <= max); + + vm.expectRevert(abi.encodeWithSelector(ProvisionManager.ProvisionManagerInvalidRange.selector, min, max)); + dataService.setVerifierCutRange(min, max); + } + function test_VerifierCut_WhenGettingTheRange() external { dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); _assert_verifierCut_range(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol index 7ff6c8246..c8721260f 100644 --- a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol +++ b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol @@ -5,6 +5,8 @@ import { GraphBaseTest } from "../GraphBase.t.sol"; import { DataServiceBaseUpgradeable } from "./implementations/DataServiceBaseUpgradeable.sol"; import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; +import { PPMMath } from "./../../contracts/libraries/PPMMath.sol"; + contract DataServiceUpgradeableTest is GraphBaseTest { function test_WhenTheContractIsDeployed() external { (DataServiceBaseUpgradeable dataService, DataServiceBaseUpgradeable implementation) = _deployDataService(); @@ -20,7 +22,7 @@ contract DataServiceUpgradeableTest is GraphBaseTest { (uint32 minVerifierCut, uint32 maxVerifierCut) = dataService.getVerifierCutRange(); assertEq(minVerifierCut, type(uint32).min); - assertEq(maxVerifierCut, type(uint32).max); + assertEq(maxVerifierCut, uint32(PPMMath.MAX_PPM)); (uint64 minThawingPeriod, uint64 maxThawingPeriod) = dataService.getThawingPeriodRange(); assertEq(minThawingPeriod, type(uint64).min); diff --git a/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol b/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol index eef727465..9f4a8822b 100644 --- a/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol @@ -5,6 +5,8 @@ import { GraphBaseTest } from "../../GraphBase.t.sol"; import { DataServiceImpPausableUpgradeable } from "../implementations/DataServiceImpPausableUpgradeable.sol"; import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; +import { PPMMath } from "./../../../contracts/libraries/PPMMath.sol"; + contract DataServicePausableUpgradeableTest is GraphBaseTest { function test_WhenTheContractIsDeployed() external { ( @@ -23,7 +25,7 @@ contract DataServicePausableUpgradeableTest is GraphBaseTest { (uint32 minVerifierCut, uint32 maxVerifierCut) = dataService.getVerifierCutRange(); assertEq(minVerifierCut, type(uint32).min); - assertEq(maxVerifierCut, type(uint32).max); + assertEq(maxVerifierCut, uint32(PPMMath.MAX_PPM)); (uint64 minThawingPeriod, uint64 maxThawingPeriod) = dataService.getThawingPeriodRange(); assertEq(minThawingPeriod, type(uint64).min); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index a3b9d1541..27fdefd2f 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -464,11 +464,11 @@ contract SubgraphService is /** * @notice Getter for the accepted verifier cut range for provisions * @return min The minimum verifier cut which is defined by {DisputeManager-getVerifierCut} - * @return max The maximum is unbounded + * @return max The maximum is 100% in PPM */ function _getVerifierCutRange() internal view override returns (uint32 min, uint32 max) { uint32 verifierCut = _disputeManager().getVerifierCut(); - return (verifierCut, type(uint32).max); + return (verifierCut, uint32(PPMMath.MAX_PPM)); } /** From d7814eaeb98fdf25551a7957cf2e0a35fea954c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 19 Aug 2024 15:24:20 -0300 Subject: [PATCH 156/277] fix: use isvalidPPM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/utilities/ProvisionManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index c89e9e473..ad18bee93 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -198,7 +198,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa */ function _setVerifierCutRange(uint32 _min, uint32 _max) internal { require(_min <= _max, ProvisionManagerInvalidRange(_min, _max)); - require(_max <= PPMMath.MAX_PPM, ProvisionManagerInvalidRange(_min, _max)); + require(PPMMath.isValidPPM(_max), ProvisionManagerInvalidRange(_min, _max)); minimumVerifierCut = _min; maximumVerifierCut = _max; emit VerifierCutRangeSet(_min, _max); From 4c58b6203fd522324db7639e2d5beb705cb67587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 11:55:09 -0300 Subject: [PATCH 157/277] fix: cap slash amount to a stake snapshot percentage (OZ M-02) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/data-service/DataService.sol | 28 +++ .../data-service/interfaces/IDataService.sol | 27 +++ .../utilities/ProvisionManager.sol | 35 ---- .../contracts/DisputeManager.sol | 66 +++++-- .../contracts/interfaces/IDisputeManager.sol | 12 +- .../test/disputes/accept.t.sol | 165 +++++++++++++++--- .../test/disputes/cancel.t.sol | 4 +- .../subgraph-service/test/disputes/draw.t.sol | 4 +- .../test/shared/SubgraphServiceShared.t.sol | 5 + 9 files changed, 261 insertions(+), 85 deletions(-) diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index b2bc32d95..c87cf5e40 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -47,4 +47,32 @@ abstract contract DataService is GraphDirectory, ProvisionManager, DataServiceV1 */ // solhint-disable-next-line func-name-mixedcase function __DataService_init_unchained() internal onlyInitializing {} + + /** + * @notice See {IDataService-getThawingPeriodRange}. + */ + function getThawingPeriodRange() external view returns (uint64, uint64) { + return _getThawingPeriodRange(); + } + + /** + * @notice See {IDataService-getVerifierCutRange}. + */ + function getVerifierCutRange() external view returns (uint32, uint32) { + return _getVerifierCutRange(); + } + + /** + * @notice See {IDataService-getProvisionTokensRange}. + */ + function getProvisionTokensRange() external view returns (uint256, uint256) { + return _getProvisionTokensRange(); + } + + /** + * @notice See {IDataService-getDelegationRatio}. + */ + function getDelegationRatio() external view returns (uint32) { + return _getDelegationRatio(); + } } diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index 69b4fdf1c..1627c8651 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -139,4 +139,31 @@ interface IDataService { * @param data Custom data, usage defined by the data service. */ function slash(address serviceProvider, bytes calldata data) external; + + /** + * @notice External getter for the thawing period range + * @return Minimum thawing period allowed + * @return Maximum thawing period allowed + */ + function getThawingPeriodRange() external view returns (uint64, uint64); + + /** + * @notice External getter for the verifier cut range + * @return Minimum verifier cut allowed + * @return Maximum verifier cut allowed + */ + function getVerifierCutRange() external view returns (uint32, uint32); + + /** + * @notice External getter for the provision tokens range + * @return Minimum provision tokens allowed + * @return Maximum provision tokens allowed + */ + function getProvisionTokensRange() external view returns (uint256, uint256); + + /** + * @notice External getter for the delegation ratio + * @return The delegation ratio + */ + function getDelegationRatio() external view returns (uint32); } diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index ad18bee93..36c3f70b0 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -101,41 +101,6 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa _; } - /** - * @notice External getter for the thawing period range - * @return Minimum thawing period allowed - * @return Maximum thawing period allowed - */ - function getThawingPeriodRange() external view returns (uint64, uint64) { - return _getThawingPeriodRange(); - } - - /** - * @notice External getter for the verifier cut range - * @return Minimum verifier cut allowed - * @return Maximum verifier cut allowed - */ - function getVerifierCutRange() external view returns (uint32, uint32) { - return _getVerifierCutRange(); - } - - /** - * @notice External getter for the provision tokens range - * @return Minimum provision tokens allowed - * @return Maximum provision tokens allowed - */ - function getProvisionTokensRange() external view returns (uint256, uint256) { - return _getProvisionTokensRange(); - } - - /** - * @notice External getter for the delegation ratio - * @return The delegation ratio - */ - function getDelegationRatio() external view returns (uint32) { - return _getDelegationRatio(); - } - /** * @notice Initializes the contract and any parent contracts. */ diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index b1d894061..6d4577153 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -9,6 +9,7 @@ import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { MathUtils } from "@graphprotocol/horizon/contracts/libraries/MathUtils.sol"; import { Allocation } from "./libraries/Allocation.sol"; import { Attestation } from "./libraries/Attestation.sol"; @@ -229,7 +230,7 @@ contract DisputeManager is dispute.status = IDisputeManager.DisputeStatus.Accepted; // Slash - uint256 tokensToReward = _slashIndexer(dispute.indexer, tokensSlash); + uint256 tokensToReward = _slashIndexer(dispute.indexer, tokensSlash, dispute.stakeSnapshot); // Give the fisherman their reward and their deposit back _graphToken().pushTokens(dispute.fisherman, tokensToReward + dispute.deposit); @@ -364,6 +365,15 @@ contract DisputeManager is return disputePeriod; } + /** + * @notice Get the stake snapshot for an indexer. + * @param indexer The indexer address + */ + function getStakeSnapshot(address indexer) external view override returns (uint256) { + IHorizonStaking.Provision memory provision = _graphStaking().getProvision(indexer, address(subgraphService)); + return _getStakeSnapshot(indexer, provision.tokens); + } + /** * @notice Checks if two attestations are conflicting. * @param attestation1 The first attestation @@ -465,6 +475,7 @@ contract DisputeManager is require(!isDisputeCreated(disputeId), DisputeManagerDisputeAlreadyCreated(disputeId)); // Store dispute + uint256 stakeSnapshot = _getStakeSnapshot(indexer, provision.tokens); disputes[disputeId] = Dispute( indexer, _fisherman, @@ -472,7 +483,8 @@ contract DisputeManager is 0, // no related dispute, DisputeType.QueryDispute, IDisputeManager.DisputeStatus.Pending, - block.timestamp + block.timestamp, + stakeSnapshot ); emit QueryDisputeCreated( @@ -481,7 +493,8 @@ contract DisputeManager is _fisherman, _deposit, _attestation.subgraphDeploymentId, - _attestationData + _attestationData, + stakeSnapshot ); return disputeId; @@ -516,6 +529,7 @@ contract DisputeManager is require(provision.tokens != 0, DisputeManagerZeroTokens()); // Store dispute + uint256 stakeSnapshot = _getStakeSnapshot(indexer, provision.tokens); disputes[disputeId] = Dispute( alloc.indexer, _fisherman, @@ -523,10 +537,11 @@ contract DisputeManager is 0, DisputeType.IndexingDispute, IDisputeManager.DisputeStatus.Pending, - block.timestamp + block.timestamp, + stakeSnapshot ); - emit IndexingDisputeCreated(disputeId, alloc.indexer, _fisherman, _deposit, _allocationId, _poi); + emit IndexingDisputeCreated(disputeId, alloc.indexer, _fisherman, _deposit, _allocationId, _poi, stakeSnapshot); return disputeId; } @@ -578,21 +593,24 @@ contract DisputeManager is * Give the challenger a reward equal to the fishermanRewardPercentage of slashed amount * @param _indexer Address of the indexer * @param _tokensSlash Amount of tokens to slash from the indexer + * @param _tokensStakeSnapshot Snapshot of the indexer's stake at the time of the dispute creation */ - function _slashIndexer(address _indexer, uint256 _tokensSlash) private returns (uint256) { + function _slashIndexer( + address _indexer, + uint256 _tokensSlash, + uint256 _tokensStakeSnapshot + ) private returns (uint256) { // Get slashable amount for indexer IHorizonStaking.Provision memory provision = _graphStaking().getProvision(_indexer, address(subgraphService)); - IHorizonStaking.DelegationPool memory pool = _graphStaking().getDelegationPool( - _indexer, - address(subgraphService) - ); - uint256 totalProvisionTokens = provision.tokens + pool.tokens; // slashable tokens - // Get slash amount - uint256 maxTokensSlash = uint256(maxSlashingCut).mulPPM(totalProvisionTokens); - require(_tokensSlash != 0 && _tokensSlash <= maxTokensSlash, DisputeManagerInvalidTokensSlash(_tokensSlash)); + // Ensure slash amount is within the cap + uint256 maxTokensSlash = _tokensStakeSnapshot.mulPPM(maxSlashingCut); + require( + _tokensSlash != 0 && _tokensSlash <= maxTokensSlash, + DisputeManagerInvalidTokensSlash(_tokensSlash, maxTokensSlash) + ); - // Rewards amount can only be extracted from service poriver tokens so + // Rewards amount can only be extracted from service provider tokens so // we grab the minimum between the slash amount and indexer's tokens uint256 maxRewardableTokens = Math.min(_tokensSlash, provision.tokens); uint256 tokensRewards = uint256(fishermanRewardCut).mulPPM(maxRewardableTokens); @@ -678,4 +696,22 @@ contract DisputeManager is // this is so the check returns false when rejecting the related dispute. return relatedId != 0 && disputes[relatedId].status == IDisputeManager.DisputeStatus.Pending; } + + /** + * @notice Get the total stake snapshot for and indexer. + * @dev A few considerations: + * - We include both indexer and delegators stake. + * - Thawing stake is not excluded from the snapshot. + * - Delegators stake is capped at the delegation ratio to prevent delegators from inflating the snapshot + * to increase the indexer slash amount. + * @param _indexer Indexer address + * @param _indexerStake Indexer's stake + * @return Total stake snapshot + */ + function _getStakeSnapshot(address _indexer, uint256 _indexerStake) private view returns (uint256) { + uint256 delegatorsStake = _graphStaking().getDelegationPool(_indexer, address(subgraphService)).tokens; + uint256 delegatorsStakeMax = _indexerStake * uint256(subgraphService.getDelegationRatio()); + uint256 stakeSnapshot = _indexerStake + MathUtils.min(delegatorsStake, delegatorsStakeMax); + return stakeSnapshot; + } } diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 86b7783d8..b0616824d 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -38,6 +38,8 @@ interface IDisputeManager { DisputeStatus status; // Timestamp when the dispute was created uint256 createdAt; + // Stake snapshot of the indexer at the time of the dispute (includes delegation up to the delegation ratio) + uint256 stakeSnapshot; } /** @@ -87,7 +89,8 @@ interface IDisputeManager { address indexed fisherman, uint256 tokens, bytes32 subgraphDeploymentId, - bytes attestation + bytes attestation, + uint256 stakeSnapshot ); /** @@ -101,7 +104,8 @@ interface IDisputeManager { address indexed fisherman, uint256 tokens, address allocationId, - bytes32 poi + bytes32 poi, + uint256 stakeSnapshot ); /** @@ -150,7 +154,7 @@ interface IDisputeManager { error DisputeManagerInvalidMinimumDeposit(uint256 minimumDeposit); error DisputeManagerInvalidFishermanReward(uint32 cut); error DisputeManagerInvalidMaxSlashingCut(uint32 maxSlashingCut); - error DisputeManagerInvalidTokensSlash(uint256 tokensSlash); + error DisputeManagerInvalidTokensSlash(uint256 tokensSlash, uint256 maxTokensSlash); error DisputeManagerDisputeNotPending(IDisputeManager.DisputeStatus status); error DisputeManagerInsufficientDeposit(uint256 deposit, uint256 minimumDeposit); error DisputeManagerDisputeAlreadyCreated(bytes32 disputeId); @@ -222,4 +226,6 @@ interface IDisputeManager { Attestation.State memory attestation1, Attestation.State memory attestation2 ) external pure returns (bool); + + function getStakeSnapshot(address indexer) external view returns (uint256); } diff --git a/packages/subgraph-service/test/disputes/accept.t.sol b/packages/subgraph-service/test/disputes/accept.t.sol index 6292e65a4..ee9bbec27 100644 --- a/packages/subgraph-service/test/disputes/accept.t.sol +++ b/packages/subgraph-service/test/disputes/accept.t.sol @@ -6,6 +6,7 @@ import "forge-std/Test.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; import { DisputeManagerTest } from "./DisputeManager.t.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { using PPMMath for uint256; @@ -17,9 +18,17 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_IndexingDispute( uint256 tokens, uint256 tokensDispute, - uint256 tokensSlash + uint256 tokensSlash, + uint256 delegationAmount ) public useIndexer useAllocation(tokens) { - tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); + + resetPrank(users.delegator); + _delegate(delegationAmount); + + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); + uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); + tokensSlash = bound(tokensSlash, 1, tokensSlashCap); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); @@ -28,17 +37,25 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { resetPrank(users.arbitrator); disputeManager.acceptDispute(disputeID, tokensSlash); - uint256 fishermanReward = tokensSlash.mulPPM(fishermanRewardPercentage); + uint256 fishermanReward = Math.min(tokensSlash, tokens).mulPPM(fishermanRewardPercentage); uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; - assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance, "Fisherman should receive 50% of slashed tokens."); + assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance); } function testAccept_QueryDispute( uint256 tokens, uint256 tokensDispute, - uint256 tokensSlash + uint256 tokensSlash, + uint256 delegationAmount ) public useIndexer useAllocation(tokens) { - tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); + + resetPrank(users.delegator); + _delegate(delegationAmount); + + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); + uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); + tokensSlash = bound(tokensSlash, 1, tokensSlashCap); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); @@ -47,16 +64,24 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { resetPrank(users.arbitrator); disputeManager.acceptDispute(disputeID, tokensSlash); - uint256 fishermanReward = tokensSlash.mulPPM(fishermanRewardPercentage); + uint256 fishermanReward = Math.min(tokensSlash, tokens).mulPPM(fishermanRewardPercentage); uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; - assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance, "Fisherman should receive 50% of slashed tokens."); + assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance); } function testAccept_QueryDisputeConflicting( uint256 tokens, - uint256 tokensSlash + uint256 tokensSlash, + uint256 delegationAmount ) public useIndexer useAllocation(tokens) { - tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); + + resetPrank(users.delegator); + _delegate(delegationAmount); + + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); + uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); + tokensSlash = bound(tokensSlash, 1, tokensSlashCap); bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); @@ -79,48 +104,132 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { resetPrank(users.arbitrator); disputeManager.acceptDispute(disputeID1, tokensSlash); - uint256 fishermanReward = tokensSlash.mulPPM(fishermanRewardPercentage); + uint256 fishermanReward = Math.min(tokensSlash, tokens).mulPPM(fishermanRewardPercentage); uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; - assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance, "Fisherman should receive 50% of slashed tokens."); + assertEq( + token.balanceOf(users.fisherman), + fishermanExpectedBalance, + "Fisherman should receive 50% of slashed tokens." + ); - (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + (, , , , , IDisputeManager.DisputeStatus status1, , ) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, , ) = disputeManager.disputes(disputeID2); assertTrue(status1 == IDisputeManager.DisputeStatus.Accepted, "Dispute 1 should be accepted."); assertTrue(status2 == IDisputeManager.DisputeStatus.Rejected, "Dispute 2 should be rejected."); } - function testAccept_RevertIf_CallerIsNotArbitrator( + function testAccept_IndexingDispute_RevertIf_SlashAmountTooHigh( uint256 tokens, uint256 tokensDispute, - uint256 tokensSlash + uint256 tokensSlash, + uint256 delegationAmount ) public useIndexer useAllocation(tokens) { - tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); + + resetPrank(users.delegator); + _delegate(delegationAmount); + + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); + uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); + tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); - // attempt to accept dispute as fisherman - resetPrank(users.fisherman); - vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + resetPrank(users.arbitrator); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidTokensSlash.selector, + tokensSlash, + tokensSlashCap + ); + vm.expectRevert(expectedError); disputeManager.acceptDispute(disputeID, tokensSlash); } - function testAccept_RevertWhen_SlashingOverMaxSlashPercentage( + function testAccept_QueryDispute_RevertIf_SlashAmountTooHigh( uint256 tokens, uint256 tokensDispute, - uint256 tokensSlash + uint256 tokensSlash, + uint256 delegationAmount + ) public useIndexer useAllocation(tokens) { + delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); + + resetPrank(users.delegator); + _delegate(delegationAmount); + + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); + uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); + tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + + bytes32 disputeID = _createQueryDispute(tokensDispute); + + resetPrank(users.arbitrator); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidTokensSlash.selector, + tokensSlash, + tokensSlashCap + ); + vm.expectRevert(expectedError); + disputeManager.acceptDispute(disputeID, tokensSlash); + } + + function testAccept_ConflictingQueryDispute_RevertIf_SlashAmountTooHigh( + uint256 tokens, + uint256 tokensDispute, + uint256 tokensSlash, + uint256 delegationAmount ) public useIndexer useAllocation(tokens) { - tokensSlash = bound(tokensSlash, uint256(maxSlashingPercentage).mulPPM(tokens) + 1, type(uint256).max); + delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); + + resetPrank(users.delegator); + _delegate(delegationAmount); + + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); + uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); + tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI101"), tokensDispute); - // max slashing percentage is 50% + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + responseCID1, + subgraphDeploymentId, + responseCID2, + subgraphDeploymentId + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( + attestationData1, + attestationData2 + ); + resetPrank(users.arbitrator); bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerInvalidTokensSlash.selector, - tokensSlash + IDisputeManager.DisputeManagerInvalidTokensSlash.selector, + tokensSlash, + tokensSlashCap ); vm.expectRevert(expectedError); + disputeManager.acceptDispute(disputeID1, tokensSlash); + } + + function testAccept_RevertIf_CallerIsNotArbitrator( + uint256 tokens, + uint256 tokensDispute, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + tokensDispute = bound(tokensDispute, minimumDeposit, tokens); + + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + + // attempt to accept dispute as fisherman + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); disputeManager.acceptDispute(disputeID, tokensSlash); } } diff --git a/packages/subgraph-service/test/disputes/cancel.t.sol b/packages/subgraph-service/test/disputes/cancel.t.sol index 741feda16..f61e7c099 100644 --- a/packages/subgraph-service/test/disputes/cancel.t.sol +++ b/packages/subgraph-service/test/disputes/cancel.t.sol @@ -54,8 +54,8 @@ contract DisputeManagerCancelDisputeTest is DisputeManagerTest { disputeManager.cancelDispute(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + (, , , , , IDisputeManager.DisputeStatus status1, ,) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ,) = disputeManager.disputes(disputeID2); assertTrue(status1 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 1 should be cancelled."); assertTrue(status2 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 2 should be cancelled."); } diff --git a/packages/subgraph-service/test/disputes/draw.t.sol b/packages/subgraph-service/test/disputes/draw.t.sol index 746d25ebd..e28561b10 100644 --- a/packages/subgraph-service/test/disputes/draw.t.sol +++ b/packages/subgraph-service/test/disputes/draw.t.sol @@ -50,8 +50,8 @@ contract DisputeManagerDrawDisputeTest is DisputeManagerTest { resetPrank(users.arbitrator); disputeManager.drawDispute(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status1, ) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ) = disputeManager.disputes(disputeID2); + (, , , , , IDisputeManager.DisputeStatus status1, ,) = disputeManager.disputes(disputeID1); + (, , , , , IDisputeManager.DisputeStatus status2, ,) = disputeManager.disputes(disputeID2); assertTrue(status1 == IDisputeManager.DisputeStatus.Drawn, "Dispute 1 should be drawn."); assertTrue(status2 == IDisputeManager.DisputeStatus.Drawn, "Dispute 2 should be drawn."); } diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index a67a151c1..8c0b9d0fe 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -70,6 +70,11 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { subgraphService.startService(users.indexer, data); } + function _delegate(uint256 tokens) internal { + token.approve(address(staking), tokens); + staking.delegate(users.indexer, address(subgraphService), tokens, 0); + } + /* * PRIVATE */ From 94fe5a0ce0f3c6e76275ed053a3917914abbf7fd Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 15 Aug 2024 17:11:16 -0300 Subject: [PATCH 158/277] fix: early return in Staking withdraw (OZ M-03) --- .../contracts/staking/HorizonStaking.sol | 22 ++- .../horizon/test/staking/HorizonStaking.t.sol | 19 ++- .../horizon/test/staking/stake/unstake.t.sol | 128 ++++++++++++++++-- .../horizon/test/staking/stake/withdraw.t.sol | 59 ++++++++ packages/horizon/test/utils/Constants.sol | 1 + 5 files changed, 205 insertions(+), 24 deletions(-) create mode 100644 packages/horizon/test/staking/stake/withdraw.t.sol diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 6ad6dec7c..79093fa9c 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -147,7 +147,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice See {IHorizonStakingMain-withdraw}. */ function withdraw() external override notPaused { - _withdraw(msg.sender, true); + _withdraw(msg.sender); } /* @@ -540,8 +540,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit StakeWithdrawn(serviceProvider, _tokens); } else { // Before locking more tokens, withdraw any unlocked ones if possible - if (sp.__DEPRECATED_tokensLockedUntil != 0 && block.number >= sp.__DEPRECATED_tokensLockedUntil) { - _withdraw(serviceProvider, false); + if (sp.__DEPRECATED_tokensLocked != 0 && block.number >= sp.__DEPRECATED_tokensLockedUntil) { + _withdraw(serviceProvider); } // TODO remove after the transition period // Take into account period averaging for multiple unstake requests @@ -564,22 +564,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice See {IHorizonStakingMain-withdraw}. * @param _serviceProvider Address of service provider to withdraw funds from - * @param _revertIfThawing If true, the function will revert if the tokens are still thawing */ - function _withdraw(address _serviceProvider, bool _revertIfThawing) private { + function _withdraw(address _serviceProvider) private { // Get tokens available for withdraw and update balance ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; uint256 tokensToWithdraw = sp.__DEPRECATED_tokensLocked; require(tokensToWithdraw != 0, HorizonStakingInvalidZeroTokens()); - - if (_revertIfThawing) { - require( - block.timestamp >= sp.__DEPRECATED_tokensLockedUntil, - HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) - ); - } else { - return; - } + require( + block.number >= sp.__DEPRECATED_tokensLockedUntil, + HorizonStakingStillThawing(sp.__DEPRECATED_tokensLockedUntil) + ); // Reset locked tokens sp.__DEPRECATED_tokensLocked = 0; diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index ec3248f39..98a1ca203 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -107,4 +107,21 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { function _getDelegationPool(address verifier) internal view returns (DelegationPool memory) { return staking.getDelegationPool(users.indexer, verifier); } -} \ No newline at end of file + + function _storeServiceProvider( + address _indexer, + uint256 _tokensStaked, + uint256 _tokensAllocated, + uint256 _tokensLocked, + uint256 _tokensLockedUntil, + uint256 _tokensProvisioned + ) internal { + uint256 serviceProviderSlot = 14; + bytes32 serviceProviderBaseSlot = keccak256(abi.encode(_indexer, serviceProviderSlot)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot)), bytes32(_tokensStaked)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 1), bytes32(_tokensAllocated)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 2), bytes32(_tokensLocked)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 3), bytes32(_tokensLockedUntil)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 4), bytes32(_tokensProvisioned)); + } +} diff --git a/packages/horizon/test/staking/stake/unstake.t.sol b/packages/horizon/test/staking/stake/unstake.t.sol index 140148d24..c5d44a3fb 100644 --- a/packages/horizon/test/staking/stake/unstake.t.sol +++ b/packages/horizon/test/staking/stake/unstake.t.sol @@ -3,31 +3,141 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; +import { MathUtils } from "../../../contracts/libraries/MathUtils.sol"; + import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingUnstakeTest is HorizonStakingTest { + function _unstakeTokens(uint256 _tokens) private { + uint256 previousIndexerTokens = token.balanceOf(users.indexer); + uint256 previousIndexerIdleStake = staking.getIdleStake(users.indexer); + + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.StakeWithdrawn(users.indexer, _tokens); + staking.unstake(_tokens); + + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, previousIndexerIdleStake - _tokens); + + uint256 newIndexerBalance = token.balanceOf(users.indexer); + assertEq(newIndexerBalance - previousIndexerTokens, _tokens); + } + + function _unstakeDuringLockingPeriod( + uint256 _tokens, + uint256 _tokensStillThawing, + uint256 _tokensToWithdraw, + uint32 _oldLockingPeriod + ) private { + uint256 previousIndexerTokens = token.balanceOf(users.indexer); + uint256 previousIndexerIdleStake = staking.getIdleStake(users.indexer); + + vm.expectEmit(address(staking)); + uint256 lockingPeriod = block.number + THAWING_PERIOD_IN_BLOCKS; + if (_tokensStillThawing > 0) { + lockingPeriod = block.number + MathUtils.weightedAverageRoundingUp( + MathUtils.diffOrZero(_oldLockingPeriod, block.number), + _tokensStillThawing, + THAWING_PERIOD_IN_BLOCKS, + _tokens + ); + } + emit IHorizonStakingMain.StakeLocked(users.indexer, _tokens + _tokensStillThawing, lockingPeriod); + staking.unstake(_tokens); + + uint256 idleStake = staking.getIdleStake(users.indexer); + assertEq(idleStake, previousIndexerIdleStake - _tokens); + + uint256 newIndexerBalance = token.balanceOf(users.indexer); + assertEq(newIndexerBalance - previousIndexerTokens, _tokensToWithdraw); + } + + function _storeDeprecatedThawingPeriod(uint32 _thawingPeriod) private { + uint256 slot = 13; + bytes32 value = bytes32(uint256(_thawingPeriod)); + vm.store(address(staking), bytes32(slot), value); + } + /* * TESTS */ function testUnstake_Tokens( - uint256 amount, + uint256 tokens, + uint256 tokensToUnstake, uint32 maxVerifierCut, uint64 thawingPeriod ) public useIndexer - useProvision(amount, maxVerifierCut, thawingPeriod) - useThawAndDeprovision(amount, thawingPeriod) + useProvision(tokens, maxVerifierCut, thawingPeriod) { - uint256 previousIndexerTokens = token.balanceOf(users.indexer); - staking.unstake(amount); - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, 0 ether); + tokensToUnstake = bound(tokensToUnstake, 1, tokens); + _createThawRequest(tokens); + skip(thawingPeriod + 1); + _deprovision(0); + _unstakeTokens(tokensToUnstake); + } - uint256 newIndexerBalance = token.balanceOf(users.indexer); - assertEq(newIndexerBalance - previousIndexerTokens, amount); + function testUnstake_LockingPeriodGreaterThanZero_TokensDoneThawing( + uint256 tokens, + uint256 tokensToUnstake, + uint256 tokensLocked + ) + public + useIndexer + { + // bounds + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + tokensToUnstake = bound(tokensToUnstake, 1, tokens); + tokensLocked = bound(tokensLocked, 1, MAX_STAKING_TOKENS); + + // vm.store to simulate locked tokens with past locking period + _storeDeprecatedThawingPeriod(THAWING_PERIOD_IN_BLOCKS); + token.transfer(address(staking), tokensLocked); + _storeServiceProvider(users.indexer, tokensLocked, 0, tokensLocked, block.number, 0); + + // create provision, thaw request and deprovision + _createProvision(subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + _createThawRequest(tokens); + skip(MAX_THAWING_PERIOD + 1); + _deprovision(0); + + // unstake + _unstakeDuringLockingPeriod(tokensToUnstake, 0, tokensLocked, 0); + } + + function testUnstake_LockingPeriodGreaterThanZero_TokensStillThawing( + uint256 tokens, + uint256 tokensToUnstake, + uint256 tokensThawing, + uint32 tokensThawingUntilBlock + ) + public + useIndexer + { + // bounds + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + tokensToUnstake = bound(tokensToUnstake, 1, tokens); + tokensThawing = bound(tokensThawing, 1, MAX_STAKING_TOKENS); + vm.assume(tokensThawingUntilBlock > block.number); + vm.assume(tokensThawingUntilBlock < block.number + THAWING_PERIOD_IN_BLOCKS); + + // vm.store to simulate locked tokens still thawing + _storeDeprecatedThawingPeriod(THAWING_PERIOD_IN_BLOCKS); + token.transfer(address(staking), tokensThawing); + _storeServiceProvider(users.indexer, tokensThawing, 0, tokensThawing, tokensThawingUntilBlock, 0); + + // create provision, thaw request and deprovision + _createProvision(subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + _createThawRequest(tokens); + skip(MAX_THAWING_PERIOD + 1); + _deprovision(0); + + // unstake + _unstakeDuringLockingPeriod(tokensToUnstake, tokensThawing, 0, tokensThawingUntilBlock); } function testUnstake_RevertWhen_ZeroTokens( diff --git a/packages/horizon/test/staking/stake/withdraw.t.sol b/packages/horizon/test/staking/stake/withdraw.t.sol new file mode 100644 index 000000000..73a96b542 --- /dev/null +++ b/packages/horizon/test/staking/stake/withdraw.t.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingWithdrawTest is HorizonStakingTest { + + /* + * HELPERS + */ + + function _withdrawLockedTokens(uint256 tokens) private { + uint256 previousIndexerTokens = token.balanceOf(users.indexer); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.StakeWithdrawn(users.indexer, tokens); + staking.withdraw(); + uint256 newIndexerBalance = token.balanceOf(users.indexer); + assertEq(newIndexerBalance - previousIndexerTokens, tokens); + } + + /* + * TESTS + */ + + function testWithdraw_Tokens(uint256 tokens, uint256 tokensLocked) public useIndexer { + vm.assume(tokens > 0); + tokensLocked = bound(tokensLocked, 1, tokens); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); + _storeServiceProvider(users.indexer, tokens, 0, tokensLocked, block.timestamp, 0); + _withdrawLockedTokens(tokensLocked); + } + + function testWithdraw_RevertWhen_ZeroTokens(uint256 tokens) public useIndexer { + vm.assume(tokens > 0); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); + _storeServiceProvider(users.indexer, tokens, 0, 0, block.timestamp, 0); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidZeroTokens.selector + )); + staking.withdraw(); + } + + function testWithdraw_RevertWhen_StillThawing(uint256 tokens, uint256 tokensLocked) public useIndexer { + vm.assume(tokens > 0); + tokensLocked = bound(tokensLocked, 1, tokens); + _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); + uint256 thawUntil = block.timestamp + 1; + _storeServiceProvider(users.indexer, tokens, 0, tokensLocked, thawUntil, 0); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingStillThawing.selector, + thawUntil + )); + staking.withdraw(); + } +} \ No newline at end of file diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index a5fc1fe27..29daaaa96 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -15,6 +15,7 @@ abstract contract Constants { uint32 internal constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% in parts per million uint64 internal constant MAX_THAWING_PERIOD = 28 days; uint256 internal constant MIN_DELEGATION = 1 ether; + uint32 internal constant THAWING_PERIOD_IN_BLOCKS = 300; // Epoch manager uint256 internal constant EPOCH_LENGTH = 1; // Rewards manager From cab507f92c46af03684c3916e53399219aa08757 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 16 Aug 2024 12:43:09 -0300 Subject: [PATCH 159/277] fix: slashing reverts when exceeding provision balance (OZ M-05) --- .../internal/IHorizonStakingMain.sol | 8 - .../contracts/staking/HorizonStaking.sol | 6 +- .../horizon/test/staking/slash/slash.t.sol | 166 +++++++++--------- 3 files changed, 89 insertions(+), 91 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 2f45ef386..28c865bf2 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -390,14 +390,6 @@ interface IHorizonStakingMain { */ error HorizonStakingInsufficientShares(uint256 shares, uint256 minShares); - // -- Errors: slashing -- - /** - * @notice Thrown when delegation pool reserves are not enough to cover slashing amount. - * @param tokens The actual token amount in the delegation pool - * @param tokensToSlash The amount to be slashed - */ - error HorizonStakingNotEnoughDelegation(uint256 tokens, uint256 tokensToSlash); - // -- Errors: thaw requests -- error HorizonStakingNothingThawing(); diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 79093fa9c..e0de847b0 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -360,9 +360,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { Provision storage prov = _provisions[serviceProvider][verifier]; DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); uint256 tokensProvisionTotal = prov.tokens + pool.tokens; - require(tokensProvisionTotal >= tokens, HorizonStakingInsufficientTokens(prov.tokens, tokens)); + require(tokensProvisionTotal != 0, HorizonStakingInsufficientTokens(tokensProvisionTotal, tokens)); - uint256 tokensToSlash = tokens; + uint256 tokensToSlash = MathUtils.min(tokens, tokensProvisionTotal); uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); if (providerTokensSlashed > 0) { uint256 maxVerifierTokens = prov.tokens.mulPPM(prov.maxVerifierCut); @@ -390,10 +390,10 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { emit ProvisionSlashed(serviceProvider, verifier, providerTokensSlashed); } + // Since tokensToSlash is already limited above, this subtraction will remain within pool.tokens. tokensToSlash = tokensToSlash - providerTokensSlashed; if (tokensToSlash > 0) { if (_delegationSlashingEnabled) { - require(pool.tokens >= tokensToSlash, HorizonStakingNotEnoughDelegation(pool.tokens, tokensToSlash)); _graphToken().burnTokens(tokensToSlash); uint256 delegationFractionSlashed = (tokensToSlash * FIXED_POINT_PRECISION) / pool.tokens; pool.tokens = pool.tokens - tokensToSlash; diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 758ebc1cf..2fe8c4ef6 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -3,6 +3,9 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; +import { MathUtils } from "../../../contracts/libraries/MathUtils.sol"; + import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingSlashTest is HorizonStakingTest { @@ -24,8 +27,43 @@ contract HorizonStakingSlashTest is HorizonStakingTest { * HELPERS */ - function _slash(uint256 amount, uint256 verifierCutAmount) private { - staking.slash(users.indexer, amount, verifierCutAmount, subgraphDataServiceAddress); + function _slash(uint256 tokens, uint256 verifierCutAmount) private { + uint256 beforeProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + uint256 beforeDelegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + bool isDelegationSlashingEnabled = staking.isDelegationSlashingEnabled(); + + // Calculate expected tokens after slashing + uint256 providerTokensSlashed = MathUtils.min(beforeProviderTokens, tokens); + uint256 expectedProviderTokensAfterSlashing = beforeProviderTokens - providerTokensSlashed; + + uint256 delegationTokensSlashed = MathUtils.min(beforeDelegationTokens, tokens - providerTokensSlashed); + uint256 expectedDelegationTokensAfterSlashing = beforeDelegationTokens - (isDelegationSlashingEnabled ? delegationTokensSlashed : 0); + + vm.expectEmit(address(staking)); + if (verifierCutAmount > 0) { + emit IHorizonStakingMain.VerifierTokensSent(users.indexer, subgraphDataServiceAddress, subgraphDataServiceAddress, verifierCutAmount); + } + emit IHorizonStakingMain.ProvisionSlashed(users.indexer, subgraphDataServiceAddress, providerTokensSlashed); + + if (isDelegationSlashingEnabled) { + emit IHorizonStakingMain.DelegationSlashed(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); + } else { + emit IHorizonStakingMain.DelegationSlashingSkipped(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); + } + staking.slash(users.indexer, tokens, verifierCutAmount, subgraphDataServiceAddress); + + if (!isDelegationSlashingEnabled) { + expectedDelegationTokensAfterSlashing = beforeDelegationTokens; + } + + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, expectedProviderTokensAfterSlashing); + + uint256 delegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(delegationTokens, expectedDelegationTokensAfterSlashing); + + uint256 verifierTokens = token.balanceOf(subgraphDataServiceAddress); + assertEq(verifierTokens, verifierCutAmount); } /* @@ -33,114 +71,82 @@ contract HorizonStakingSlashTest is HorizonStakingTest { */ function testSlash_Tokens( - uint256 amount, + uint256 tokens, uint32 maxVerifierCut, - uint256 slashAmount, + uint256 slashTokens, uint256 verifierCutAmount - ) public useIndexer useProvision(amount, maxVerifierCut, 0) { + ) public useIndexer useProvision(tokens, maxVerifierCut, 0) { verifierCutAmount = bound(verifierCutAmount, 0, maxVerifierCut); - slashAmount = bound(slashAmount, 1, amount); - uint256 maxVerifierTokens = (slashAmount * maxVerifierCut) / MAX_PPM; + slashTokens = bound(slashTokens, 1, tokens); + uint256 maxVerifierTokens = (slashTokens * maxVerifierCut) / MAX_PPM; vm.assume(verifierCutAmount <= maxVerifierTokens); vm.startPrank(subgraphDataServiceAddress); - _slash(slashAmount, verifierCutAmount); - - uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(provisionTokens, amount - slashAmount); - - uint256 verifierTokens = token.balanceOf(subgraphDataServiceAddress); - assertEq(verifierTokens, verifierCutAmount); + _slash(slashTokens, verifierCutAmount); } - function testSlash_RevertWhen_TooManyTokens( - uint256 amount, - uint32 maxVerifierCut, - uint256 verifierCutAmount - ) public useIndexer useProvision(amount, maxVerifierCut, 0) { - uint256 maxVerifierTokens = (amount * maxVerifierCut) / MAX_PPM; - verifierCutAmount = bound(verifierCutAmount, maxVerifierTokens + 1, MAX_STAKING_TOKENS); - - vm.startPrank(subgraphDataServiceAddress); - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingTooManyTokens(uint256,uint256)", - verifierCutAmount, - maxVerifierTokens - ); - vm.expectRevert(expectedError); - _slash(amount, verifierCutAmount); - } - - function testSlash_DelegationDisabled_SlashingOverProvisionTokens( - uint256 amount, - uint256 slashAmount, + function testSlash_DelegationDisabled_SlashingOverProviderTokens( + uint256 tokens, + uint256 slashTokens, uint256 verifierCutAmount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(false) { - delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); - slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); + uint256 delegationTokens + ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(false) { + vm.assume(slashTokens > tokens); + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); - uint256 maxVerifierTokens = (amount * MAX_MAX_VERIFIER_CUT) / MAX_PPM; + uint256 maxVerifierTokens = (tokens * MAX_MAX_VERIFIER_CUT) / MAX_PPM; vm.assume(verifierCutAmount <= maxVerifierTokens); resetPrank(users.delegator); - _delegate(delegationAmount, subgraphDataServiceAddress); + _delegate(delegationTokens, subgraphDataServiceAddress); vm.startPrank(subgraphDataServiceAddress); - _slash(slashAmount, verifierCutAmount); - - uint256 provisionProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(provisionProviderTokens, 0 ether); - - uint256 verifierTokens = token.balanceOf(address(subgraphDataServiceAddress)); - assertEq(verifierTokens, verifierCutAmount); - - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - // No slashing occurred for delegation - assertEq(delegatedTokens, delegationAmount); + _slash(slashTokens, verifierCutAmount); } - function testSlash_DelegationEnabled_SlashingOverProvisionTokens( - uint256 amount, - uint256 slashAmount, + function testSlash_DelegationEnabled_SlashingOverProviderTokens( + uint256 tokens, + uint256 slashTokens, uint256 verifierCutAmount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(true) { - delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); - slashAmount = bound(slashAmount, amount + 1, amount + delegationAmount); + uint256 delegationTokens + ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(true) { + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + slashTokens = bound(slashTokens, tokens + 1, tokens + delegationTokens); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); - uint256 maxVerifierTokens = (amount * MAX_MAX_VERIFIER_CUT) / MAX_PPM; + uint256 maxVerifierTokens = (tokens * MAX_MAX_VERIFIER_CUT) / MAX_PPM; vm.assume(verifierCutAmount <= maxVerifierTokens); resetPrank(users.delegator); - _delegate(delegationAmount, subgraphDataServiceAddress); + _delegate(delegationTokens, subgraphDataServiceAddress); vm.startPrank(subgraphDataServiceAddress); - _slash(slashAmount, verifierCutAmount); - - uint256 provisionProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(provisionProviderTokens, 0 ether); - - uint256 verifierTokens = token.balanceOf(address(subgraphDataServiceAddress)); - assertEq(verifierTokens, verifierCutAmount); + _slash(slashTokens, verifierCutAmount); + } - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - uint256 slashedDelegation = slashAmount - amount; - assertEq(delegatedTokens, delegationAmount - slashedDelegation); + function testSlash_OverProvisionSize( + uint256 tokens, + uint256 slashTokens, + uint256 delegationTokens + ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) { + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + vm.assume(slashTokens > tokens + delegationTokens); + + vm.startPrank(subgraphDataServiceAddress); + _slash(slashTokens, 0); } function testSlash_RevertWhen_NoProvision( - uint256 amount, - uint256 slashAmount - ) public useIndexer useStake(amount) { - slashAmount = bound(slashAmount, 1, amount); - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokens(uint256,uint256)", - 0 ether, - slashAmount + uint256 tokens, + uint256 slashTokens + ) public useIndexer useStake(tokens) { + vm.assume(slashTokens > 0); + bytes memory expectedError = abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInsufficientTokens.selector, + 0, + slashTokens ); vm.expectRevert(expectedError); vm.startPrank(subgraphDataServiceAddress); - _slash(slashAmount, 0); + staking.slash(users.indexer, slashTokens, 0, subgraphDataServiceAddress); } } \ No newline at end of file From 66975489d680ad197dc4ba295a70e51f75674c18 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Mon, 19 Aug 2024 16:41:33 -0300 Subject: [PATCH 160/277] fix: revert when delegating, undelegating or withdrawing from an invalid delegation pool (OZ M-06) --- .../internal/IHorizonStakingMain.sol | 7 ++ .../contracts/staking/HorizonStaking.sol | 7 ++ .../horizon/test/staking/HorizonStaking.t.sol | 71 ++++++++++++++++-- .../test/staking/delegation/delegate.t.sol | 30 +++++++- .../test/staking/delegation/undelegate.t.sol | 35 +++++---- .../test/staking/delegation/withdraw.t.sol | 72 ++++++++++++------- .../horizon/test/staking/slash/slash.t.sol | 49 ------------- 7 files changed, 176 insertions(+), 95 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 28c865bf2..2ec440263 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -390,6 +390,13 @@ interface IHorizonStakingMain { */ error HorizonStakingInsufficientShares(uint256 shares, uint256 minShares); + /** + * @notice Thrown when as a result of slashing delegation pool has no tokens but has shares. + * @param serviceProvider The service provider address + * @param verifier The verifier address + */ + error HorizonStakingInvalidDelegationPool(address serviceProvider, address verifier); + // -- Errors: thaw requests -- error HorizonStakingNothingThawing(); diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index e0de847b0..a8abafa7b 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -713,6 +713,11 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); DelegationInternal storage delegation = pool.delegators[msg.sender]; + require( + pool.tokens != 0 || pool.shares == 0, + HorizonStakingInvalidDelegationPool(_serviceProvider, _verifier) + ); + // Calculate shares to issue uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); require(shares != 0 && shares >= _minSharesOut, HorizonStakingSlippageProtection(shares, _minSharesOut)); @@ -735,6 +740,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); DelegationInternal storage delegation = pool.delegators[msg.sender]; require(delegation.shares >= _shares, HorizonStakingInsufficientShares(delegation.shares, _shares)); + require(pool.tokens != 0, HorizonStakingInvalidDelegationPool(_serviceProvider, _verifier)); uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); @@ -776,6 +782,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 _nThawRequests ) private { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); + require(pool.tokens != 0, HorizonStakingInvalidDelegationPool(_serviceProvider, _verifier)); uint256 tokensThawed = 0; uint256 sharesThawing = pool.sharesThawing; diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index 98a1ca203..dde585a58 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -3,7 +3,11 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { IHorizonStakingTypes } from "../../contracts/interfaces/internal/IHorizonStakingTypes.sol"; +import { LinkedList } from "../../contracts/libraries/LinkedList.sol"; +import { MathUtils } from "../../contracts/libraries/MathUtils.sol"; + import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { @@ -74,6 +78,15 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { _; } + modifier useDelegationSlashing(bool enabled) { + address msgSender; + (, msgSender,) = vm.readCallers(); + resetPrank(users.governor); + staking.setDelegationSlashingEnabled(enabled); + resetPrank(msgSender); + _; + } + /* * HELPERS */ @@ -91,17 +104,26 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { staking.deprovision(users.indexer, subgraphDataServiceAddress, nThawRequests); } - function _delegate(uint256 amount, address verifier) internal { - token.approve(address(staking), amount); - staking.delegate(users.indexer, verifier, amount, 0); + function _delegate(uint256 _tokens, address _verifier) internal { + token.approve(address(staking), _tokens); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.TokensDelegated(users.indexer, _verifier, users.delegator, _tokens); + staking.delegate(users.indexer, _verifier, _tokens, 0); + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, _verifier); + assertEq(delegatedTokens, _tokens); } function _getDelegation(address verifier) internal view returns (Delegation memory) { return staking.getDelegation(users.indexer, verifier, users.delegator); } - function _undelegate(uint256 shares, address verifier) internal { - staking.undelegate(users.indexer, verifier, shares); + function _undelegate(uint256 _shares, address _verifier) internal { + staking.undelegate(users.indexer, _verifier, _shares); + + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, _verifier, users.delegator); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + + assertEq(thawRequest.shares, _shares); } function _getDelegationPool(address verifier) internal view returns (DelegationPool memory) { @@ -124,4 +146,43 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 3), bytes32(_tokensLockedUntil)); vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 4), bytes32(_tokensProvisioned)); } + + function _slash(uint256 tokens, uint256 verifierCutAmount) internal { + uint256 beforeProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + uint256 beforeDelegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + bool isDelegationSlashingEnabled = staking.isDelegationSlashingEnabled(); + + // Calculate expected tokens after slashing + uint256 providerTokensSlashed = MathUtils.min(beforeProviderTokens, tokens); + uint256 expectedProviderTokensAfterSlashing = beforeProviderTokens - providerTokensSlashed; + + uint256 delegationTokensSlashed = MathUtils.min(beforeDelegationTokens, tokens - providerTokensSlashed); + uint256 expectedDelegationTokensAfterSlashing = beforeDelegationTokens - (isDelegationSlashingEnabled ? delegationTokensSlashed : 0); + + vm.expectEmit(address(staking)); + if (verifierCutAmount > 0) { + emit IHorizonStakingMain.VerifierTokensSent(users.indexer, subgraphDataServiceAddress, subgraphDataServiceAddress, verifierCutAmount); + } + emit IHorizonStakingMain.ProvisionSlashed(users.indexer, subgraphDataServiceAddress, providerTokensSlashed); + + if (isDelegationSlashingEnabled) { + emit IHorizonStakingMain.DelegationSlashed(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); + } else { + emit IHorizonStakingMain.DelegationSlashingSkipped(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); + } + staking.slash(users.indexer, tokens, verifierCutAmount, subgraphDataServiceAddress); + + if (!isDelegationSlashingEnabled) { + expectedDelegationTokensAfterSlashing = beforeDelegationTokens; + } + + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(provisionTokens, expectedProviderTokensAfterSlashing); + + uint256 delegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + assertEq(delegationTokens, expectedDelegationTokensAfterSlashing); + + uint256 verifierTokens = token.balanceOf(subgraphDataServiceAddress); + assertEq(verifierTokens, verifierCutAmount); + } } diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index c254756fc..4e3a1d23c 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; + import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDelegateTest is HorizonStakingTest { @@ -14,9 +16,10 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { function testDelegate_Tokens( uint256 amount, uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(delegatedTokens, delegationAmount); + ) public useIndexer useProvision(amount, 0, 0) { + delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); + resetPrank(users.delegator); + _delegate(delegationAmount, subgraphDataServiceAddress); } function testDelegate_RevertWhen_ZeroTokens( @@ -57,4 +60,25 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceLegacyAddress); assertEq(delegatedTokens, delegationAmount); } + + function testDelegate_RevertWhen_InvalidPool( + uint256 tokens, + uint256 delegationTokens + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + resetPrank(users.delegator); + _delegate(delegationTokens, subgraphDataServiceAddress); + + resetPrank(subgraphDataServiceAddress); + _slash(tokens + delegationTokens, 0); + + resetPrank(users.delegator); + token.approve(address(staking), delegationTokens); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + users.indexer, + subgraphDataServiceAddress + )); + staking.delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 5dcc85183..98b00668f 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -3,9 +3,9 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; -import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingUndelegateTest is HorizonStakingTest { @@ -20,11 +20,6 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { resetPrank(users.delegator); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); _undelegate(delegation.shares, subgraphDataServiceAddress); - - LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceAddress, users.delegator); - ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); - - assertEq(thawRequest.shares, delegation.shares); } function testUndelegate_RevertWhen_ZeroTokens( @@ -52,7 +47,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { overDelegationShares ); vm.expectRevert(expectedError); - _undelegate(overDelegationShares, subgraphDataServiceAddress); + staking.undelegate(users.indexer, subgraphDataServiceAddress, overDelegationShares); } function testUndelegate_RevertWhen_UndelegateLeavesInsufficientTokens( @@ -73,7 +68,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { MIN_DELEGATION ); vm.expectRevert(expectedError); - _undelegate(withdrawShares, subgraphDataServiceAddress); + staking.undelegate(users.indexer, subgraphDataServiceAddress, withdrawShares); } function testUndelegate_LegacySubgraphService( @@ -88,10 +83,26 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { _delegate(delegationAmount, subgraphDataServiceLegacyAddress); Delegation memory delegation = _getDelegation(subgraphDataServiceLegacyAddress); _undelegate(delegation.shares, subgraphDataServiceLegacyAddress); + } - LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceLegacyAddress, users.delegator); - ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + function testUndelegate_RevertWhen_InvalidPool( + uint256 tokens, + uint256 delegationTokens + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + resetPrank(users.delegator); + _delegate(delegationTokens, subgraphDataServiceAddress); - assertEq(thawRequest.shares, delegation.shares); + resetPrank(subgraphDataServiceAddress); + _slash(tokens + delegationTokens, 0); + + resetPrank(users.delegator); + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + users.indexer, + subgraphDataServiceAddress + )); + staking.undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 8110c3d9a..ea26a7120 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -3,10 +3,11 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { HorizonStakingTest } from "../HorizonStaking.t.sol"; - +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { /* @@ -35,8 +36,21 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { * HELPERS */ - function _withdrawDelegated(address verifier) private { - staking.withdrawDelegated(users.indexer, verifier, address(0x0), 0, 0); + function _withdrawDelegated(address _verifier, address _newIndexer) private { + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, _verifier, users.delegator); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + + uint256 previousBalance = token.balanceOf(users.delegator); + uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest, _verifier); + staking.withdrawDelegated(users.indexer, _verifier, _newIndexer, 0, 0); + + if (_newIndexer != address(0)) { + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(_newIndexer, _verifier); + assertEq(delegatedTokens, expectedTokens); + } else { + uint256 newBalance = token.balanceOf(users.delegator); + assertEq(newBalance - previousBalance, expectedTokens); + } } function _expectedTokensFromThawRequest(ThawRequest memory thawRequest, address verifier) private view returns (uint256) { @@ -75,12 +89,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { skip(thawRequest.thawingUntil + 1); - uint256 previousBalance = token.balanceOf(users.delegator); - uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest, subgraphDataServiceAddress); - _withdrawDelegated(subgraphDataServiceAddress); - - uint256 newBalance = token.balanceOf(users.delegator); - assertEq(newBalance - previousBalance, expectedTokens); + _withdrawDelegated(subgraphDataServiceAddress, address(0)); } function testWithdrawDelegation_RevertWhen_NotThawing( @@ -93,7 +102,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - _withdrawDelegated(subgraphDataServiceAddress); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); } function testWithdrawDelegation_MoveToNewServiceProvider( @@ -109,15 +118,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { // Setup new service provider address newIndexer = _setupNewIndexer(10_000_000 ether); - - uint256 previousBalance = token.balanceOf(users.delegator); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); - - uint256 newBalance = token.balanceOf(users.delegator); - assertEq(newBalance, previousBalance); - - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(newIndexer, subgraphDataServiceAddress); - assertEq(delegatedTokens, delegationAmount); + _withdrawDelegated(subgraphDataServiceAddress, newIndexer); } function testWithdrawDelegation_ZeroTokens( @@ -130,7 +131,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useUndelegate(delegationAmount) { uint256 previousBalance = token.balanceOf(users.delegator); - _withdrawDelegated(subgraphDataServiceAddress); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); // Nothing changed since thawing period haven't finished uint256 newBalance = token.balanceOf(users.delegator); @@ -173,11 +174,30 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { skip(thawRequest.thawingUntil + 1); - uint256 previousBalance = token.balanceOf(users.delegator); - uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest, subgraphDataServiceLegacyAddress); - _withdrawDelegated(subgraphDataServiceLegacyAddress); + _withdrawDelegated(subgraphDataServiceLegacyAddress, address(0)); + } - uint256 newBalance = token.balanceOf(users.delegator); - assertEq(newBalance - previousBalance, expectedTokens); + function testWithdrawDelegation_RevertWhen_InvalidPool( + uint256 tokens, + uint256 delegationTokens + ) public useIndexer useProvision(tokens, 0, MAX_THAWING_PERIOD) useDelegationSlashing(true) { + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + resetPrank(users.delegator); + _delegate(delegationTokens, subgraphDataServiceAddress); + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + _undelegate(delegation.shares, subgraphDataServiceAddress); + + skip(MAX_THAWING_PERIOD + 1); + + resetPrank(subgraphDataServiceAddress); + _slash(tokens + delegationTokens, 0); + + resetPrank(users.delegator); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + users.indexer, + subgraphDataServiceAddress + )); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 2fe8c4ef6..7797186b4 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; -import { MathUtils } from "../../../contracts/libraries/MathUtils.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; @@ -14,58 +13,10 @@ contract HorizonStakingSlashTest is HorizonStakingTest { * MODIFIERS */ - modifier useDelegationSlashing(bool enabled) { - address msgSender; - (, msgSender,) = vm.readCallers(); - vm.startPrank(users.governor); - staking.setDelegationSlashingEnabled(enabled); - vm.startPrank(msgSender); - _; - } - /* * HELPERS */ - function _slash(uint256 tokens, uint256 verifierCutAmount) private { - uint256 beforeProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - uint256 beforeDelegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - bool isDelegationSlashingEnabled = staking.isDelegationSlashingEnabled(); - - // Calculate expected tokens after slashing - uint256 providerTokensSlashed = MathUtils.min(beforeProviderTokens, tokens); - uint256 expectedProviderTokensAfterSlashing = beforeProviderTokens - providerTokensSlashed; - - uint256 delegationTokensSlashed = MathUtils.min(beforeDelegationTokens, tokens - providerTokensSlashed); - uint256 expectedDelegationTokensAfterSlashing = beforeDelegationTokens - (isDelegationSlashingEnabled ? delegationTokensSlashed : 0); - - vm.expectEmit(address(staking)); - if (verifierCutAmount > 0) { - emit IHorizonStakingMain.VerifierTokensSent(users.indexer, subgraphDataServiceAddress, subgraphDataServiceAddress, verifierCutAmount); - } - emit IHorizonStakingMain.ProvisionSlashed(users.indexer, subgraphDataServiceAddress, providerTokensSlashed); - - if (isDelegationSlashingEnabled) { - emit IHorizonStakingMain.DelegationSlashed(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); - } else { - emit IHorizonStakingMain.DelegationSlashingSkipped(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); - } - staking.slash(users.indexer, tokens, verifierCutAmount, subgraphDataServiceAddress); - - if (!isDelegationSlashingEnabled) { - expectedDelegationTokensAfterSlashing = beforeDelegationTokens; - } - - uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(provisionTokens, expectedProviderTokensAfterSlashing); - - uint256 delegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(delegationTokens, expectedDelegationTokensAfterSlashing); - - uint256 verifierTokens = token.balanceOf(subgraphDataServiceAddress); - assertEq(verifierTokens, verifierCutAmount); - } - /* * TESTS */ From 50a8fa317fea240f767b2ed58baa34b6e9ec6da0 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 20 Aug 2024 16:07:30 -0300 Subject: [PATCH 161/277] fix: rename error --- .../contracts/interfaces/internal/IHorizonStakingMain.sol | 2 +- packages/horizon/contracts/staking/HorizonStaking.sol | 6 +++--- packages/horizon/test/staking/delegation/delegate.t.sol | 2 +- packages/horizon/test/staking/delegation/undelegate.t.sol | 2 +- packages/horizon/test/staking/delegation/withdraw.t.sol | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 2ec440263..25c5f85aa 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -395,7 +395,7 @@ interface IHorizonStakingMain { * @param serviceProvider The service provider address * @param verifier The verifier address */ - error HorizonStakingInvalidDelegationPool(address serviceProvider, address verifier); + error HorizonStakingInvalidDelegationPoolState(address serviceProvider, address verifier); // -- Errors: thaw requests -- diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index a8abafa7b..f6fd5cff3 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -715,7 +715,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { require( pool.tokens != 0 || pool.shares == 0, - HorizonStakingInvalidDelegationPool(_serviceProvider, _verifier) + HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier) ); // Calculate shares to issue @@ -740,7 +740,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); DelegationInternal storage delegation = pool.delegators[msg.sender]; require(delegation.shares >= _shares, HorizonStakingInsufficientShares(delegation.shares, _shares)); - require(pool.tokens != 0, HorizonStakingInvalidDelegationPool(_serviceProvider, _verifier)); + require(pool.tokens != 0, HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier)); uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); @@ -782,7 +782,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 _nThawRequests ) private { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); - require(pool.tokens != 0, HorizonStakingInvalidDelegationPool(_serviceProvider, _verifier)); + require(pool.tokens != 0, HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier)); uint256 tokensThawed = 0; uint256 sharesThawing = pool.sharesThawing; diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 4e3a1d23c..183463717 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -75,7 +75,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { resetPrank(users.delegator); token.approve(address(staking), delegationTokens); vm.expectRevert(abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, users.indexer, subgraphDataServiceAddress )); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 98b00668f..5025ccc39 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -99,7 +99,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { resetPrank(users.delegator); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); vm.expectRevert(abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, users.indexer, subgraphDataServiceAddress )); diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index ea26a7120..6ec26c937 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -194,7 +194,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { resetPrank(users.delegator); vm.expectRevert(abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, users.indexer, subgraphDataServiceAddress )); From bdaa2c42038197d417aaca412d495d5d2876f226 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 20 Aug 2024 16:33:27 -0300 Subject: [PATCH 162/277] fix: check for shares thawing --- .../contracts/staking/HorizonStaking.sol | 2 +- .../test/staking/delegation/delegate.t.sol | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index f6fd5cff3..4d3349b7a 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -714,7 +714,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { DelegationInternal storage delegation = pool.delegators[msg.sender]; require( - pool.tokens != 0 || pool.shares == 0, + pool.tokens != 0 || (pool.shares == 0 && pool.sharesThawing == 0), HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier) ); diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 183463717..11a823a32 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -81,4 +81,27 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { )); staking.delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); } + + function testDelegate_RevertWhen_ThawingShares_InvalidPool( + uint256 tokens, + uint256 delegationTokens + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { + delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + resetPrank(users.delegator); + _delegate(delegationTokens, subgraphDataServiceAddress); + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + _undelegate(delegation.shares, subgraphDataServiceAddress); + + resetPrank(subgraphDataServiceAddress); + _slash(tokens + delegationTokens, 0); + + resetPrank(users.delegator); + token.approve(address(staking), delegationTokens); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, + users.indexer, + subgraphDataServiceAddress + )); + staking.delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + } } \ No newline at end of file From 3ab169b893aa4cc1c16f4b6090e83d8b5899e0aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 22 Aug 2024 12:09:50 -0300 Subject: [PATCH 163/277] fix: return tokens to delegator when bridging if the pool is invalid (OZ M-06) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../horizon/contracts/staking/HorizonStakingExtension.sol | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 3aa425154..6e4894bcc 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -348,6 +348,13 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; IHorizonStakingTypes.DelegationInternal storage delegation = pool.delegators[_delegationData.delegator]; + // If pool is in an invalid state, return the tokens to the delegator + if (pool.tokens == 0 && (pool.shares == 0 || pool.sharesThawing == 0)) { + _graphToken().transfer(_delegationData.delegator, _tokens); + emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _tokens); + return; + } + // Calculate shares to issue (without applying any delegation tax) uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / pool.tokens); From 5a06dd8697f2a84dbc2b4af5e9e109095f3e344f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 22 Aug 2024 14:15:44 -0300 Subject: [PATCH 164/277] fix: invalid pool detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/contracts/staking/HorizonStakingExtension.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 6e4894bcc..41dda175f 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -349,7 +349,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon IHorizonStakingTypes.DelegationInternal storage delegation = pool.delegators[_delegationData.delegator]; // If pool is in an invalid state, return the tokens to the delegator - if (pool.tokens == 0 && (pool.shares == 0 || pool.sharesThawing == 0)) { + if (pool.tokens == 0 && (pool.shares != 0 || pool.sharesThawing != 0)) { _graphToken().transfer(_delegationData.delegator, _tokens); emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _tokens); return; From 1650a91979c9793fe6771d79b8e5ad5265d193ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 20 Aug 2024 16:48:54 -0300 Subject: [PATCH 165/277] fix: wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../internal/IHorizonStakingExtension.sol | 3 +- packages/horizon/test/GraphBase.t.sol | 8 +- .../horizon/test/staking/HorizonStaking.t.sol | 217 ++++++++++++++++-- .../test/staking/delegation/addToPool.t.sol | 2 + .../test/staking/delegation/delegate.t.sol | 46 ++-- .../test/staking/delegation/undelegate.t.sol | 64 ++++-- .../test/staking/delegation/withdraw.t.sol | 10 +- .../horizon/test/staking/slash/slash.t.sol | 4 +- .../test/staking/transfer-tools/ttools.t.sol | 76 ++++++ 9 files changed, 359 insertions(+), 71 deletions(-) create mode 100644 packages/horizon/test/staking/transfer-tools/ttools.t.sol diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 80fc52ea0..2df5cd82a 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -3,12 +3,13 @@ pragma solidity 0.8.26; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; +import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; /** * @title Interface for {HorizonStakingExtension} contract. * @notice Provides functions for managing legacy allocations and transfer tools. */ -interface IHorizonStakingExtension is IRewardsIssuer { +interface IHorizonStakingExtension is IRewardsIssuer, IL2StakingBase { /** * @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() diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index fec51c345..7126c5313 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -43,6 +43,10 @@ abstract contract GraphBaseTest is Utils, Constants { address subgraphDataServiceLegacyAddress = makeAddr("subgraphDataServiceLegacyAddress"); address subgraphDataServiceAddress = makeAddr("subgraphDataServiceAddress"); + + // We use these addresses to mock calls from the counterpart staking contract + address graphTokenGatewayAddress = makeAddr("GraphTokenGateway"); + address counterpartStaking = makeAddr("counterpartStaking"); /* Users */ @@ -144,7 +148,7 @@ abstract contract GraphBaseTest is Utils, Constants { controller.setContractProxy(keccak256("EpochManager"), address(epochManager)); controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); controller.setContractProxy(keccak256("Curation"), address(curation)); - controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); + controller.setContractProxy(keccak256("GraphTokenGateway"), graphTokenGatewayAddress); controller.setContractProxy(keccak256("GraphProxyAdmin"), address(proxyAdmin)); resetPrank(users.deployer); @@ -171,6 +175,8 @@ abstract contract GraphBaseTest is Utils, Constants { proxyAdmin.upgrade(stakingProxy, address(stakingBase)); proxyAdmin.acceptProxy(stakingBase, stakingProxy); staking = IHorizonStaking(address(stakingProxy)); + + staking.setCounterpartStakingAddress(address(counterpartStaking)); } function setupProtocol() private { diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index dde585a58..64dbc1630 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { stdStorage, StdStorage } from "forge-std/Test.sol"; import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { IHorizonStakingTypes } from "../../contracts/interfaces/internal/IHorizonStakingTypes.sol"; @@ -11,6 +12,7 @@ import { MathUtils } from "../../contracts/libraries/MathUtils.sol"; import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { + using stdStorage for StdStorage; /* * MODIFIERS @@ -60,18 +62,18 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { modifier useDelegation(uint256 delegationAmount) { address msgSender; - (, msgSender,) = vm.readCallers(); + (, msgSender, ) = vm.readCallers(); vm.assume(delegationAmount > MIN_DELEGATION); vm.assume(delegationAmount <= MAX_STAKING_TOKENS); vm.startPrank(users.delegator); - _delegate(delegationAmount, subgraphDataServiceAddress); + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); vm.startPrank(msgSender); _; } modifier useLockedVerifier(address verifier) { address msgSender; - (, msgSender,) = vm.readCallers(); + (, msgSender, ) = vm.readCallers(); resetPrank(users.governor); staking.setAllowedLockedVerifier(verifier, true); resetPrank(msgSender); @@ -80,7 +82,7 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { modifier useDelegationSlashing(bool enabled) { address msgSender; - (, msgSender,) = vm.readCallers(); + (, msgSender, ) = vm.readCallers(); resetPrank(users.governor); staking.setDelegationSlashingEnabled(enabled); resetPrank(msgSender); @@ -104,26 +106,167 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { staking.deprovision(users.indexer, subgraphDataServiceAddress, nThawRequests); } - function _delegate(uint256 _tokens, address _verifier) internal { - token.approve(address(staking), _tokens); - vm.expectEmit(address(staking)); - emit IHorizonStakingMain.TokensDelegated(users.indexer, _verifier, users.delegator, _tokens); - staking.delegate(users.indexer, _verifier, _tokens, 0); - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, _verifier); - assertEq(delegatedTokens, _tokens); + function _delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) internal { + __delegate(serviceProvider, verifier, tokens, minSharesOut, false); } - function _getDelegation(address verifier) internal view returns (Delegation memory) { - return staking.getDelegation(users.indexer, verifier, users.delegator); + function _delegateLegacy(address serviceProvider, uint256 tokens) internal { + __delegate(serviceProvider, subgraphDataServiceLegacyAddress, tokens, 0, true); + } + + + struct DelegateData { + DelegationPool pool; + Delegation delegation; + uint256 storagePoolTokens; + uint256 delegatedTokens; + uint256 delegatorBalance; + uint256 stakingBalance; + } + + function __delegate( + address serviceProvider, + address verifier, + uint256 tokens, + uint256 minSharesOut, + bool legacy + ) internal { + (, address delegator, ) = vm.readCallers(); + + // before + DelegateData memory beforeData = DelegateData({ + pool: staking.getDelegationPool(serviceProvider, verifier), + delegation: staking.getDelegation(serviceProvider, verifier, delegator), + storagePoolTokens: uint256(vm.load(address(staking), _getSlotPoolTokens(serviceProvider, verifier, legacy))), + delegatedTokens: staking.getDelegatedTokensAvailable(serviceProvider, verifier), + delegatorBalance: token.balanceOf(delegator), + stakingBalance: token.balanceOf(address(staking)) + }); + + uint256 calcShares = (beforeData.pool.tokens == 0) + ? tokens + : ((tokens * beforeData.pool.shares) / (beforeData.pool.tokens - beforeData.pool.tokensThawing)); + + // delegate + token.approve(address(staking), tokens); + vm.expectEmit(); + emit IHorizonStakingMain.TokensDelegated(serviceProvider, verifier, delegator, tokens); + if (legacy) { + staking.delegate(serviceProvider, tokens); + } else { + staking.delegate(serviceProvider, verifier, tokens, minSharesOut); + } + + // after + DelegateData memory afterData = DelegateData({ + pool: staking.getDelegationPool(serviceProvider, verifier), + delegation: staking.getDelegation(serviceProvider, verifier, delegator), + storagePoolTokens: uint256(vm.load(address(staking), _getSlotPoolTokens(serviceProvider, verifier, legacy))), + delegatedTokens: staking.getDelegatedTokensAvailable(serviceProvider, verifier), + delegatorBalance: token.balanceOf(delegator), + stakingBalance: token.balanceOf(address(staking)) + }); + + uint256 deltaShares = afterData.delegation.shares - beforeData.delegation.shares; + + // assertions + assertEq(beforeData.pool.tokens + tokens, afterData.pool.tokens); + assertEq(beforeData.pool.shares + calcShares, afterData.pool.shares); + assertEq(beforeData.pool.tokensThawing, afterData.pool.tokensThawing); + assertEq(beforeData.pool.sharesThawing, afterData.pool.sharesThawing); + assertGe(deltaShares, minSharesOut); + assertEq(calcShares, deltaShares); + assertEq(beforeData.delegatedTokens + tokens, afterData.delegatedTokens); + // Ensure correct slot is being updated, pools are stored in different storage locations for legacy subgraph data service + assertEq(beforeData.storagePoolTokens + tokens, afterData.storagePoolTokens); + assertEq(beforeData.delegatorBalance - tokens, afterData.delegatorBalance); + assertEq(beforeData.stakingBalance + tokens, afterData.stakingBalance); + } + + function _undelegate(address serviceProvider, address verifier, uint256 shares) internal { + __undelegate(serviceProvider, verifier, shares, false); + } + + function _undelegateLegacy(address serviceProvider, uint256 shares) internal { + __undelegate(serviceProvider, subgraphDataServiceLegacyAddress, shares, true); } - function _undelegate(uint256 _shares, address _verifier) internal { - staking.undelegate(users.indexer, _verifier, _shares); + function __undelegate(address serviceProvider, address verifier, uint256 shares, bool legacy) internal { + (, address delegator, ) = vm.readCallers(); + + // Delegation pool data is stored in a different storage slot for the legacy subgraph data service + bytes32 slotPoolShares; + if (legacy) { + slotPoolShares = bytes32(uint256(keccak256(abi.encode(serviceProvider, 20))) + 3); + } else { + slotPoolShares = bytes32( + uint256(keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, 33))))) + 3 + ); + } - LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, _verifier, users.delegator); - ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + // before + DelegationPool memory beforePool = staking.getDelegationPool(serviceProvider, verifier); + Delegation memory beforeDelegation = staking.getDelegation(serviceProvider, verifier, delegator); + LinkedList.List memory beforeThawRequestList = staking.getThawRequestList(serviceProvider, verifier, delegator); + uint256 beforeStoragePoolShares = uint256(vm.load(address(staking), slotPoolShares)); + uint256 beforeDelegatedTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); + + uint256 calcTokens = ((beforePool.tokens - beforePool.tokensThawing) * shares) / beforePool.shares; + uint256 calcThawingShares = beforePool.tokensThawing == 0 + ? calcTokens + : (beforePool.sharesThawing * calcTokens) / beforePool.tokensThawing; + uint64 calcThawingUntil = staking.getProvision(serviceProvider, verifier).thawingPeriod + + uint64(block.timestamp); + bytes32 calcThawRequestId = keccak256( + abi.encodePacked(serviceProvider, verifier, delegator, beforeThawRequestList.nonce) + ); + + // undelegate + vm.expectEmit(); + emit IHorizonStakingMain.ThawRequestCreated( + serviceProvider, + verifier, + delegator, + calcThawingShares, + calcThawingUntil, + calcThawRequestId + ); + vm.expectEmit(); + emit IHorizonStakingMain.TokensUndelegated(serviceProvider, verifier, delegator, calcTokens); + if (legacy) { + staking.undelegate(serviceProvider, shares); + } else { + staking.undelegate(serviceProvider, verifier, shares); + } - assertEq(thawRequest.shares, _shares); + // after + DelegationPool memory afterPool = staking.getDelegationPool(users.indexer, verifier); + Delegation memory afterDelegation = staking.getDelegation(serviceProvider, verifier, delegator); + LinkedList.List memory afterThawRequestList = staking.getThawRequestList(serviceProvider, verifier, delegator); + ThawRequest memory afterThawRequest = staking.getThawRequest(calcThawRequestId); + uint256 afterStoragePoolShares = uint256(vm.load(address(staking), slotPoolShares)); + uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); + + // assertions + assertEq(beforePool.shares, afterPool.shares + shares); + assertEq(beforePool.tokens, afterPool.tokens); + assertEq(beforePool.tokensThawing + calcTokens, afterPool.tokensThawing); + assertEq(beforePool.sharesThawing + calcThawingShares, afterPool.sharesThawing); + assertEq(beforeDelegation.shares - shares, afterDelegation.shares); + assertEq(afterThawRequest.shares, calcThawingShares); + assertEq(afterThawRequest.thawingUntil, calcThawingUntil); + assertEq(afterThawRequest.next, bytes32(0)); + assertEq(calcThawRequestId, afterThawRequestList.tail); + assertEq(beforeThawRequestList.nonce + 1, afterThawRequestList.nonce); + assertEq(beforeThawRequestList.count + 1, afterThawRequestList.count); + assertEq(afterDelegatedTokens + calcTokens, beforeDelegatedTokens); + // Ensure correct slot is being updated, pools are stored in different storage locations for legacy subgraph data service + assertEq(beforeStoragePoolShares, afterStoragePoolShares + shares); + } + + // todo remove these + function _getDelegation(address verifier) internal view returns (Delegation memory) { + return staking.getDelegation(users.indexer, verifier, users.delegator); } function _getDelegationPool(address verifier) internal view returns (DelegationPool memory) { @@ -157,32 +300,58 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { uint256 expectedProviderTokensAfterSlashing = beforeProviderTokens - providerTokensSlashed; uint256 delegationTokensSlashed = MathUtils.min(beforeDelegationTokens, tokens - providerTokensSlashed); - uint256 expectedDelegationTokensAfterSlashing = beforeDelegationTokens - (isDelegationSlashingEnabled ? delegationTokensSlashed : 0); + uint256 expectedDelegationTokensAfterSlashing = beforeDelegationTokens - + (isDelegationSlashingEnabled ? delegationTokensSlashed : 0); vm.expectEmit(address(staking)); if (verifierCutAmount > 0) { - emit IHorizonStakingMain.VerifierTokensSent(users.indexer, subgraphDataServiceAddress, subgraphDataServiceAddress, verifierCutAmount); + emit IHorizonStakingMain.VerifierTokensSent( + users.indexer, + subgraphDataServiceAddress, + subgraphDataServiceAddress, + verifierCutAmount + ); } emit IHorizonStakingMain.ProvisionSlashed(users.indexer, subgraphDataServiceAddress, providerTokensSlashed); if (isDelegationSlashingEnabled) { - emit IHorizonStakingMain.DelegationSlashed(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); + emit IHorizonStakingMain.DelegationSlashed( + users.indexer, + subgraphDataServiceAddress, + delegationTokensSlashed + ); } else { - emit IHorizonStakingMain.DelegationSlashingSkipped(users.indexer, subgraphDataServiceAddress, delegationTokensSlashed); + emit IHorizonStakingMain.DelegationSlashingSkipped( + users.indexer, + subgraphDataServiceAddress, + delegationTokensSlashed + ); } staking.slash(users.indexer, tokens, verifierCutAmount, subgraphDataServiceAddress); if (!isDelegationSlashingEnabled) { expectedDelegationTokensAfterSlashing = beforeDelegationTokens; } - + uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(provisionTokens, expectedProviderTokensAfterSlashing); uint256 delegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(delegationTokens, expectedDelegationTokensAfterSlashing); - + uint256 verifierTokens = token.balanceOf(subgraphDataServiceAddress); assertEq(verifierTokens, verifierCutAmount); } + + function _getSlotPoolTokens(address serviceProvider, address verifier, bool legacy) private returns (bytes32) { + bytes32 slotPoolTokens; + if (legacy) { + slotPoolTokens = bytes32(uint256(keccak256(abi.encode(serviceProvider, 20))) + 2); + } else { + slotPoolTokens = bytes32( + uint256(keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, 33))))) + 2 + ); + } + return slotPoolTokens; + } } diff --git a/packages/horizon/test/staking/delegation/addToPool.t.sol b/packages/horizon/test/staking/delegation/addToPool.t.sol index bdafa4046..4ef0c480a 100644 --- a/packages/horizon/test/staking/delegation/addToPool.t.sol +++ b/packages/horizon/test/staking/delegation/addToPool.t.sol @@ -62,4 +62,6 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 0); } + + // TODO: test recovering an invalid delegation pool } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 11a823a32..7136cf721 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -8,7 +8,6 @@ import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHor import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDelegateTest is HorizonStakingTest { - /* * TESTS */ @@ -16,15 +15,29 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { function testDelegate_Tokens( uint256 amount, uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) { - delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); - resetPrank(users.delegator); - _delegate(delegationAmount, subgraphDataServiceAddress); + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { } - function testDelegate_RevertWhen_ZeroTokens( - uint256 amount - ) public useIndexer useProvision(amount, 0, 0) { + function testDelegate_Tokens_WhenThawing( + uint256 amount, + uint256 delegationAmount, + uint256 undelegateAmount + ) public useIndexer useProvision(amount, 0, 1 days) { + amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); + // there is a min delegation amount of 1 ether after undelegating so we start with 1 ether + 1 wei + delegationAmount = bound(delegationAmount, 1 ether + 1 wei, MAX_STAKING_TOKENS); + + vm.startPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); + + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + undelegateAmount = bound(undelegateAmount, 1 wei, delegation.shares - 1 ether); + _undelegate(users.indexer, subgraphDataServiceAddress, undelegateAmount); + + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); + } + + function testDelegate_RevertWhen_ZeroTokens(uint256 amount) public useIndexer useProvision(amount, 0, 0) { vm.startPrank(users.delegator); bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); vm.expectRevert(expectedError); @@ -47,18 +60,13 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { staking.delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); } - function testDelegate_LegacySubgraphService( - uint256 amount, - uint256 delegationAmount - ) public useIndexer { + function testDelegate_LegacySubgraphService(uint256 amount, uint256 delegationAmount) public useIndexer { amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); - _delegate(delegationAmount, subgraphDataServiceLegacyAddress); - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceLegacyAddress); - assertEq(delegatedTokens, delegationAmount); + _delegateLegacy(users.indexer, delegationAmount); } function testDelegate_RevertWhen_InvalidPool( @@ -67,7 +75,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); - _delegate(delegationTokens, subgraphDataServiceAddress); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); resetPrank(subgraphDataServiceAddress); _slash(tokens + delegationTokens, 0); @@ -88,9 +96,9 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); - _delegate(delegationTokens, subgraphDataServiceAddress); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); - _undelegate(delegation.shares, subgraphDataServiceAddress); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); resetPrank(subgraphDataServiceAddress); _slash(tokens + delegationTokens, 0); @@ -104,4 +112,4 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { )); staking.delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 5025ccc39..4ffde07ff 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -8,7 +8,6 @@ import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHor import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingUndelegateTest is HorizonStakingTest { - /* * TESTS */ @@ -19,20 +18,54 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); - _undelegate(delegation.shares, subgraphDataServiceAddress); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); } - function testUndelegate_RevertWhen_ZeroTokens( + function testMultipleUndelegate_Tokens( + uint256 amount, + uint256 delegationAmount, + uint256 undelegateSteps + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + undelegateSteps = bound(undelegateSteps, 1, 10); + + resetPrank(users.delegator); + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + + // there is a min delegation amount of 1 ether after undelegating + uint256 undelegateAmount = (delegation.shares - 1 ether) / undelegateSteps; + for (uint i = 0; i < undelegateSteps; i++) { + _undelegate(users.indexer, subgraphDataServiceAddress, undelegateAmount); + } + } + + function testUndelegate_RevertWhen_TooManyUndelegations() + public + useIndexer + useProvision(1000 ether, 0, 0) + useDelegation(1000 ether) + { + resetPrank(users.delegator); + + for (uint i = 0; i < MAX_THAW_REQUESTS; i++) { + _undelegate(users.indexer, subgraphDataServiceAddress, 1 ether); + } + + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingTooManyThawRequests()"); + vm.expectRevert(expectedError); + staking.undelegate(users.indexer, subgraphDataServiceAddress, 1 ether); + } + + function testUndelegate_RevertWhen_ZeroShares( uint256 amount, uint256 delegationAmount ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroShares()"); vm.expectRevert(expectedError); - _undelegate(0, subgraphDataServiceAddress); + staking.undelegate(users.indexer, subgraphDataServiceAddress, 0); } - function testUndelegate_RevertWhen_OverUndelegation( + function testUndelegate_RevertWhen_OverShares( uint256 amount, uint256 delegationAmount, uint256 overDelegationShares @@ -53,12 +86,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { function testUndelegate_RevertWhen_UndelegateLeavesInsufficientTokens( uint256 delegationAmount, uint256 withdrawShares - ) - public - useIndexer - useProvision(10_000_000 ether, 0, 0) - useDelegation(delegationAmount) - { + ) public useIndexer useProvision(10_000_000 ether, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); uint256 minShares = delegationAmount - MIN_DELEGATION + 1; withdrawShares = bound(withdrawShares, minShares, delegationAmount - 1); @@ -71,18 +99,16 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { staking.undelegate(users.indexer, subgraphDataServiceAddress, withdrawShares); } - function testUndelegate_LegacySubgraphService( - uint256 amount, - uint256 delegationAmount - ) public useIndexer { + function testUndelegate_LegacySubgraphService(uint256 amount, uint256 delegationAmount) public useIndexer { amount = bound(amount, 1, MAX_STAKING_TOKENS); delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); - _delegate(delegationAmount, subgraphDataServiceLegacyAddress); + _delegateLegacy(users.indexer, delegationAmount); + Delegation memory delegation = _getDelegation(subgraphDataServiceLegacyAddress); - _undelegate(delegation.shares, subgraphDataServiceLegacyAddress); + _undelegateLegacy(users.indexer, delegation.shares); } function testUndelegate_RevertWhen_InvalidPool( @@ -91,7 +117,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); - _delegate(delegationTokens, subgraphDataServiceAddress); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); resetPrank(subgraphDataServiceAddress); _slash(tokens + delegationTokens, 0); @@ -105,4 +131,4 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { )); staking.undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 6ec26c937..cffcad565 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -28,7 +28,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { vm.assume(remainingTokens >= MIN_DELEGATION); } - _undelegate(shares, subgraphDataServiceAddress); + _undelegate(users.indexer, subgraphDataServiceAddress, shares); _; } @@ -165,9 +165,9 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { _createProvision(subgraphDataServiceLegacyAddress, 10_000_000 ether, 0, MAX_THAWING_PERIOD); resetPrank(users.delegator); - _delegate(delegationAmount, subgraphDataServiceLegacyAddress); + _delegateLegacy(users.indexer, delegationAmount); Delegation memory delegation = _getDelegation(subgraphDataServiceLegacyAddress); - _undelegate(delegation.shares, subgraphDataServiceLegacyAddress); + _undelegateLegacy(users.indexer, delegation.shares); LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceLegacyAddress, users.delegator); ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); @@ -183,9 +183,9 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { ) public useIndexer useProvision(tokens, 0, MAX_THAWING_PERIOD) useDelegationSlashing(true) { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); - _delegate(delegationTokens, subgraphDataServiceAddress); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); - _undelegate(delegation.shares, subgraphDataServiceAddress); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); skip(MAX_THAWING_PERIOD + 1); diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 7797186b4..8f7d086f5 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -49,7 +49,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { vm.assume(verifierCutAmount <= maxVerifierTokens); resetPrank(users.delegator); - _delegate(delegationTokens, subgraphDataServiceAddress); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); vm.startPrank(subgraphDataServiceAddress); _slash(slashTokens, verifierCutAmount); @@ -68,7 +68,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { vm.assume(verifierCutAmount <= maxVerifierTokens); resetPrank(users.delegator); - _delegate(delegationTokens, subgraphDataServiceAddress); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); vm.startPrank(subgraphDataServiceAddress); _slash(slashTokens, verifierCutAmount); diff --git a/packages/horizon/test/staking/transfer-tools/ttools.t.sol b/packages/horizon/test/staking/transfer-tools/ttools.t.sol new file mode 100644 index 000000000..9175f74e5 --- /dev/null +++ b/packages/horizon/test/staking/transfer-tools/ttools.t.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; + +contract HorizonStakingTransferToolsTest is HorizonStakingTest { + /* + * TESTS + */ + + function testOnTransfer_RevertWhen_InvalidCaller( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + + bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 + vm.expectRevert(bytes("ONLY_GATEWAY")); + staking.onTokenTransfer(counterpartStaking, 0, data); + } + + function testOnTransfer_RevertWhen_InvalidCounterpart( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + resetPrank(graphTokenGatewayAddress); + + bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 + vm.expectRevert(bytes("ONLY_L1_STAKING_THROUGH_BRIDGE")); + staking.onTokenTransfer(address(staking), 0, data); + } + + function testOnTransfer_RevertWhen_InvalidData( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + resetPrank(graphTokenGatewayAddress); + + vm.expectRevert(); + staking.onTokenTransfer(counterpartStaking, 0, new bytes(0)); + } + + function testOnTransfer_RevertWhen_InvalidCode( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + resetPrank(graphTokenGatewayAddress); + + bytes memory data = abi.encode(uint8(2), new bytes(0)); // Valid codes are 0 and 1 + vm.expectRevert(bytes("INVALID_CODE")); + staking.onTokenTransfer(counterpartStaking, 0, data); + } + + function testOnTransfer_ReceiveDelegation_RevertWhen_InvalidData( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + resetPrank(graphTokenGatewayAddress); + + bytes memory data = abi.encode(uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), new bytes(0)); + vm.expectRevert(); + staking.onTokenTransfer(counterpartStaking, 0, data); + } + + function testOnTransfer_ReceiveDelegation( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + resetPrank(graphTokenGatewayAddress); + + bytes memory data = abi.encode(uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), abi.encode(users.indexer, users.delegator)); + staking.onTokenTransfer(counterpartStaking, 0, data); + } +} From afe8bbcef3676df2a107594eca1d93c4a04ed9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 20 Aug 2024 18:39:17 -0300 Subject: [PATCH 166/277] fix: calculation of shares when receiving delegation from l1 (OZ H-03) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../staking/HorizonStakingExtension.sol | 4 +- .../test/staking/delegation/undelegate.t.sol | 4 +- .../test/staking/transfer-tools/ttools.t.sol | 198 ++++++++++++++---- 3 files changed, 159 insertions(+), 47 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 41dda175f..8f7ab8449 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -337,6 +337,8 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon * 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. + * @dev Note that L1 staking contract only allows delegation transfer if the indexer has already transferred, + * this means the corresponding delegation pool exists. * @param _tokens Amount of tokens that were transferred * @param _delegationData struct containing the delegator's address and the indexer's address */ @@ -356,7 +358,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon } // Calculate shares to issue (without applying any delegation tax) - uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / pool.tokens); + uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); if (shares == 0 || _tokens < MINIMUM_DELEGATION) { // If no shares would be issued (probably a rounding issue or attack), diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 4ffde07ff..8c578b768 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -25,10 +25,12 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount, uint256 undelegateSteps - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + ) public useIndexer useProvision(amount, 0, 0) { undelegateSteps = bound(undelegateSteps, 1, 10); + delegationAmount = bound(delegationAmount, MIN_DELEGATION + 10 wei, MAX_STAKING_TOKENS); resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); // there is a min delegation amount of 1 ether after undelegating diff --git a/packages/horizon/test/staking/transfer-tools/ttools.t.sol b/packages/horizon/test/staking/transfer-tools/ttools.t.sol index 9175f74e5..fcc3c7d69 100644 --- a/packages/horizon/test/staking/transfer-tools/ttools.t.sol +++ b/packages/horizon/test/staking/transfer-tools/ttools.t.sol @@ -5,72 +5,180 @@ import "forge-std/Test.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; +import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; +import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; contract HorizonStakingTransferToolsTest is HorizonStakingTest { + event Transfer(address indexed from, address indexed to, uint tokens); + /* * TESTS */ - function testOnTransfer_RevertWhen_InvalidCaller( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + function testOnTransfer_RevertWhen_InvalidCaller() public { + bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 + vm.expectRevert(bytes("ONLY_GATEWAY")); + staking.onTokenTransfer(counterpartStaking, 0, data); + } + + function testOnTransfer_RevertWhen_InvalidCounterpart() public { + resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 - vm.expectRevert(bytes("ONLY_GATEWAY")); - staking.onTokenTransfer(counterpartStaking, 0, data); + bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 + vm.expectRevert(bytes("ONLY_L1_STAKING_THROUGH_BRIDGE")); + staking.onTokenTransfer(address(staking), 0, data); } - function testOnTransfer_RevertWhen_InvalidCounterpart( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - resetPrank(graphTokenGatewayAddress); + function testOnTransfer_RevertWhen_InvalidData() public { + resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 - vm.expectRevert(bytes("ONLY_L1_STAKING_THROUGH_BRIDGE")); - staking.onTokenTransfer(address(staking), 0, data); + vm.expectRevert(); + staking.onTokenTransfer(counterpartStaking, 0, new bytes(0)); } - function testOnTransfer_RevertWhen_InvalidData( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - resetPrank(graphTokenGatewayAddress); + function testOnTransfer_RevertWhen_InvalidCode() public { + resetPrank(graphTokenGatewayAddress); - vm.expectRevert(); - staking.onTokenTransfer(counterpartStaking, 0, new bytes(0)); + bytes memory data = abi.encode(uint8(2), new bytes(0)); // Valid codes are 0 and 1 + vm.expectRevert(bytes("INVALID_CODE")); + staking.onTokenTransfer(counterpartStaking, 0, data); } - function testOnTransfer_RevertWhen_InvalidCode( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - resetPrank(graphTokenGatewayAddress); + function testOnTransfer_ReceiveDelegation_RevertWhen_InvalidData() public { + resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode(uint8(2), new bytes(0)); // Valid codes are 0 and 1 - vm.expectRevert(bytes("INVALID_CODE")); - staking.onTokenTransfer(counterpartStaking, 0, data); + bytes memory data = abi.encode(uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), new bytes(0)); + vm.expectRevert(); + staking.onTokenTransfer(counterpartStaking, 0, data); } - function testOnTransfer_ReceiveDelegation_RevertWhen_InvalidData( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - resetPrank(graphTokenGatewayAddress); + function testOnTransfer_ReceiveDelegation(uint256 amount) public { + amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); + + // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 + resetPrank(users.indexer); + _createProvision(subgraphDataServiceLegacyAddress, 100 ether, 0, 0); + + resetPrank(users.delegator); + _delegateLegacy(users.indexer, 1 ether); - bytes memory data = abi.encode(uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), new bytes(0)); - vm.expectRevert(); - staking.onTokenTransfer(counterpartStaking, 0, data); + // send amount to staking contract - this should be done by the bridge + resetPrank(users.delegator); + token.transfer(address(staking), amount); + + resetPrank(graphTokenGatewayAddress); + bytes memory data = abi.encode( + uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), + abi.encode(users.indexer, users.delegator) + ); + _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); } - function testOnTransfer_ReceiveDelegation( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { - resetPrank(graphTokenGatewayAddress); + function testOnTransfer_ReceiveDelegation_WhenThawing(uint256 amount) public { + amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); + uint256 originalDelegationAmount = 10 ether; + + // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 + resetPrank(users.indexer); + _createProvision(subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); + + resetPrank(users.delegator); + _delegateLegacy(users.indexer, originalDelegationAmount); + + // send amount to staking contract - this should be done by the bridge + resetPrank(users.delegator); + token.transfer(address(staking), amount); + + // thaw some delegation before receiving new delegation from L1 + resetPrank(users.delegator); + _undelegateLegacy(users.indexer, originalDelegationAmount / 10); + + resetPrank(graphTokenGatewayAddress); + bytes memory data = abi.encode( + uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), + abi.encode(users.indexer, users.delegator) + ); + _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); + } + + /** + * HELPERS + */ + + function _onTokenTransfer_ReceiveDelegation(address from, uint256 tokens, bytes memory data) internal { + (, bytes memory fnData) = abi.decode(data, (uint8, bytes)); + (address serviceProvider, address delegator) = abi.decode(fnData, (address, address)); + bytes32 slotPoolTokens = bytes32(uint256(keccak256(abi.encode(serviceProvider, 20))) + 2); + + // before + DelegationPool memory beforePool = staking.getDelegationPool(serviceProvider, subgraphDataServiceLegacyAddress); + Delegation memory beforeDelegation = staking.getDelegation( + serviceProvider, + subgraphDataServiceLegacyAddress, + delegator + ); + uint256 beforeStoragePoolTokens = uint256(vm.load(address(staking), slotPoolTokens)); + uint256 beforeDelegatedTokens = staking.getDelegatedTokensAvailable( + serviceProvider, + subgraphDataServiceLegacyAddress + ); + uint256 beforeDelegatorBalance = token.balanceOf(delegator); + uint256 beforeStakingBalance = token.balanceOf(address(staking)); + uint256 calcShares = (beforePool.tokens == 0) + ? tokens + : ((tokens * beforePool.shares) / (beforePool.tokens - beforePool.tokensThawing)); + + // onTokenTransfer + if (calcShares == 0 || tokens < 1 ether) { + vm.expectEmit(); + emit Transfer(address(staking), delegator, tokens); + vm.expectEmit(); + emit IL2StakingBase.TransferredDelegationReturnedToDelegator(serviceProvider, delegator, tokens); + } else { + vm.expectEmit(); + emit IHorizonStakingExtension.StakeDelegated(serviceProvider, delegator, tokens, calcShares); + } + staking.onTokenTransfer(counterpartStaking, tokens, data); + + // after + DelegationPool memory afterPool = staking.getDelegationPool(serviceProvider, subgraphDataServiceLegacyAddress); + Delegation memory afterDelegation = staking.getDelegation( + serviceProvider, + subgraphDataServiceLegacyAddress, + delegator + ); + uint256 afterStoragePoolTokens = uint256(vm.load(address(staking), slotPoolTokens)); + uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable( + serviceProvider, + subgraphDataServiceLegacyAddress + ); + uint256 afterDelegatorBalance = token.balanceOf(delegator); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + + uint256 deltaShares = afterDelegation.shares - beforeDelegation.shares; - bytes memory data = abi.encode(uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), abi.encode(users.indexer, users.delegator)); - staking.onTokenTransfer(counterpartStaking, 0, data); + // assertions + if (calcShares == 0 || tokens < 1 ether) { + assertEq(beforePool.tokens, afterPool.tokens); + assertEq(beforePool.shares, afterPool.shares); + assertEq(beforePool.tokensThawing, afterPool.tokensThawing); + assertEq(beforePool.sharesThawing, afterPool.sharesThawing); + assertEq(0, deltaShares); + assertEq(beforeDelegatedTokens, afterDelegatedTokens); + assertEq(beforeStoragePoolTokens, afterStoragePoolTokens); + assertEq(beforeDelegatorBalance + tokens, afterDelegatorBalance); + assertEq(beforeStakingBalance - tokens, afterStakingBalance); + } else { + assertEq(beforePool.tokens + tokens, afterPool.tokens); + assertEq(beforePool.shares + calcShares, afterPool.shares); + assertEq(beforePool.tokensThawing, afterPool.tokensThawing); + assertEq(beforePool.sharesThawing, afterPool.sharesThawing); + assertEq(calcShares, deltaShares); + assertEq(beforeDelegatedTokens + tokens, afterDelegatedTokens); + // Ensure correct slot is being updated, pools are stored in different storage locations for legacy subgraph data service + assertEq(beforeStoragePoolTokens + tokens, afterStoragePoolTokens); + assertEq(beforeDelegatorBalance, afterDelegatorBalance); + assertEq(beforeStakingBalance, afterStakingBalance); + } } } From 7d1b2fba5cf78a575dfec603ce5d145343ce8729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 22 Aug 2024 14:22:56 -0300 Subject: [PATCH 167/277] test: add test for receivedelegation special case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../horizon/test/staking/HorizonStaking.t.sol | 30 ++++++++-------- .../test/staking/delegation/delegate.t.sol | 4 +-- .../test/staking/delegation/undelegate.t.sol | 2 +- .../test/staking/delegation/withdraw.t.sol | 2 +- .../horizon/test/staking/slash/slash.t.sol | 8 ++--- .../test/staking/transfer-tools/ttools.t.sol | 36 +++++++++++++++++-- 6 files changed, 57 insertions(+), 25 deletions(-) diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index 64dbc1630..bf0106fca 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -290,9 +290,9 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 4), bytes32(_tokensProvisioned)); } - function _slash(uint256 tokens, uint256 verifierCutAmount) internal { - uint256 beforeProviderTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - uint256 beforeDelegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + function _slash(address serviceProvider, address verifier, uint256 tokens, uint256 verifierCutAmount) internal { + uint256 beforeProviderTokens = staking.getProviderTokensAvailable(serviceProvider, verifier); + uint256 beforeDelegationTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); bool isDelegationSlashingEnabled = staking.isDelegationSlashingEnabled(); // Calculate expected tokens after slashing @@ -306,40 +306,40 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { vm.expectEmit(address(staking)); if (verifierCutAmount > 0) { emit IHorizonStakingMain.VerifierTokensSent( - users.indexer, - subgraphDataServiceAddress, - subgraphDataServiceAddress, + serviceProvider, + verifier, + verifier, verifierCutAmount ); } - emit IHorizonStakingMain.ProvisionSlashed(users.indexer, subgraphDataServiceAddress, providerTokensSlashed); + emit IHorizonStakingMain.ProvisionSlashed(serviceProvider, verifier, providerTokensSlashed); if (isDelegationSlashingEnabled) { emit IHorizonStakingMain.DelegationSlashed( - users.indexer, - subgraphDataServiceAddress, + serviceProvider, + verifier, delegationTokensSlashed ); } else { emit IHorizonStakingMain.DelegationSlashingSkipped( - users.indexer, - subgraphDataServiceAddress, + serviceProvider, + verifier, delegationTokensSlashed ); } - staking.slash(users.indexer, tokens, verifierCutAmount, subgraphDataServiceAddress); + staking.slash(serviceProvider, tokens, verifierCutAmount, verifier); if (!isDelegationSlashingEnabled) { expectedDelegationTokensAfterSlashing = beforeDelegationTokens; } - uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); + uint256 provisionTokens = staking.getProviderTokensAvailable(serviceProvider, verifier); assertEq(provisionTokens, expectedProviderTokensAfterSlashing); - uint256 delegationTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); + uint256 delegationTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); assertEq(delegationTokens, expectedDelegationTokensAfterSlashing); - uint256 verifierTokens = token.balanceOf(subgraphDataServiceAddress); + uint256 verifierTokens = token.balanceOf(verifier); assertEq(verifierTokens, verifierCutAmount); } diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 7136cf721..939893794 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -78,7 +78,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); resetPrank(subgraphDataServiceAddress); - _slash(tokens + delegationTokens, 0); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); resetPrank(users.delegator); token.approve(address(staking), delegationTokens); @@ -101,7 +101,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); resetPrank(subgraphDataServiceAddress); - _slash(tokens + delegationTokens, 0); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); resetPrank(users.delegator); token.approve(address(staking), delegationTokens); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 8c578b768..54e16d084 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -122,7 +122,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); resetPrank(subgraphDataServiceAddress); - _slash(tokens + delegationTokens, 0); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); resetPrank(users.delegator); Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index cffcad565..dc7785ed4 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -190,7 +190,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { skip(MAX_THAWING_PERIOD + 1); resetPrank(subgraphDataServiceAddress); - _slash(tokens + delegationTokens, 0); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); resetPrank(users.delegator); vm.expectRevert(abi.encodeWithSelector( diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 8f7d086f5..1644e336e 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -33,7 +33,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { vm.assume(verifierCutAmount <= maxVerifierTokens); vm.startPrank(subgraphDataServiceAddress); - _slash(slashTokens, verifierCutAmount); + _slash(users.indexer, subgraphDataServiceAddress, slashTokens, verifierCutAmount); } function testSlash_DelegationDisabled_SlashingOverProviderTokens( @@ -52,7 +52,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); vm.startPrank(subgraphDataServiceAddress); - _slash(slashTokens, verifierCutAmount); + _slash(users.indexer, subgraphDataServiceAddress, slashTokens, verifierCutAmount); } function testSlash_DelegationEnabled_SlashingOverProviderTokens( @@ -71,7 +71,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); vm.startPrank(subgraphDataServiceAddress); - _slash(slashTokens, verifierCutAmount); + _slash(users.indexer, subgraphDataServiceAddress, slashTokens, verifierCutAmount); } function testSlash_OverProvisionSize( @@ -83,7 +83,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { vm.assume(slashTokens > tokens + delegationTokens); vm.startPrank(subgraphDataServiceAddress); - _slash(slashTokens, 0); + _slash(users.indexer, subgraphDataServiceAddress, slashTokens, 0); } function testSlash_RevertWhen_NoProvision( diff --git a/packages/horizon/test/staking/transfer-tools/ttools.t.sol b/packages/horizon/test/staking/transfer-tools/ttools.t.sol index fcc3c7d69..71bf2bb3e 100644 --- a/packages/horizon/test/staking/transfer-tools/ttools.t.sol +++ b/packages/horizon/test/staking/transfer-tools/ttools.t.sol @@ -101,6 +101,35 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); } + function testOnTransfer_ReceiveDelegation_WhenInvalidPool(uint256 amount) public useDelegationSlashing(true) { + amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); + uint256 originalDelegationAmount = 10 ether; + uint256 provisionSize = 100 ether; + + // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 + resetPrank(users.indexer); + _createProvision(subgraphDataServiceLegacyAddress, provisionSize, 0, 1 days); + + // initialize the delegation pool + resetPrank(users.delegator); + _delegateLegacy(users.indexer, originalDelegationAmount); + + // slash the entire provision + resetPrank(subgraphDataServiceLegacyAddress); + _slash(users.indexer, subgraphDataServiceLegacyAddress, provisionSize + originalDelegationAmount, 0); + + // send amount to staking contract - this should be done by the bridge + resetPrank(users.delegator); + token.transfer(address(staking), amount); + + resetPrank(graphTokenGatewayAddress); + bytes memory data = abi.encode( + uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), + abi.encode(users.indexer, users.delegator) + ); + _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); + } + /** * HELPERS */ @@ -128,8 +157,11 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { ? tokens : ((tokens * beforePool.shares) / (beforePool.tokens - beforePool.tokensThawing)); + bool earlyExit = (calcShares == 0 || tokens < 1 ether) || + (beforePool.tokens == 0 && (beforePool.shares != 0 || beforePool.sharesThawing != 0)); + // onTokenTransfer - if (calcShares == 0 || tokens < 1 ether) { + if (earlyExit) { vm.expectEmit(); emit Transfer(address(staking), delegator, tokens); vm.expectEmit(); @@ -158,7 +190,7 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { uint256 deltaShares = afterDelegation.shares - beforeDelegation.shares; // assertions - if (calcShares == 0 || tokens < 1 ether) { + if (earlyExit) { assertEq(beforePool.tokens, afterPool.tokens); assertEq(beforePool.shares, afterPool.shares); assertEq(beforePool.tokensThawing, afterPool.tokensThawing); From 4787e1290c6402640c96e26f1b491099d772cad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 21 Aug 2024 14:39:51 -0300 Subject: [PATCH 168/277] fix: remove subgraph service cut (OZ H-04) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../data-service/interfaces/IDataService.sol | 7 +- .../implementations/DataServiceBase.sol | 2 +- .../DataServiceBaseUpgradeable.sol | 2 +- .../implementations/DataServiceImpFees.sol | 2 +- .../DataServiceImpPausable.sol | 2 +- .../DataServiceImpPausableUpgradeable.sol | 2 +- .../contracts/SubgraphService.sol | 55 ++----- .../contracts/SubgraphServiceStorage.sol | 5 +- .../contracts/interfaces/ISubgraphService.sol | 42 ++--- .../test/SubgraphBaseTest.t.sol | 2 +- .../subgraphService/collect/collect.t.sol | 145 +++++++++++------- .../subgraph-service/test/utils/Constants.sol | 3 +- 12 files changed, 132 insertions(+), 137 deletions(-) diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index 1627c8651..258fc336c 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -125,8 +125,13 @@ interface IDataService { * @param serviceProvider The address of the service provider. * @param feeType The type of fee to collect as defined in {GraphPayments}. * @param data Custom data, usage defined by the data service. + * @return The amount of tokens collected. */ - function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external; + function collect( + address serviceProvider, + IGraphPayments.PaymentTypes feeType, + bytes calldata data + ) external returns (uint256); /** * @notice Slash a service provider for misbehaviour. diff --git a/packages/horizon/test/data-service/implementations/DataServiceBase.sol b/packages/horizon/test/data-service/implementations/DataServiceBase.sol index 1742efc12..b8171e649 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceBase.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBase.sol @@ -25,7 +25,7 @@ contract DataServiceBase is DataService { function stopService(address serviceProvider, bytes calldata data) external {} - function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external returns (uint256) {} function slash(address serviceProvider, bytes calldata data) external {} diff --git a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol index af0f22aaf..fbe2fe211 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol @@ -21,7 +21,7 @@ contract DataServiceBaseUpgradeable is DataService { function stopService(address serviceProvider, bytes calldata data) external {} - function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external returns (uint256) {} function slash(address serviceProvider, bytes calldata data) external {} diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol index 72574cedb..ee071c47d 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol @@ -21,7 +21,7 @@ contract DataServiceImpFees is DataServiceFees { function stopService(address serviceProvider, bytes calldata data) external {} - function collect(address serviceProvider, IGraphPayments.PaymentTypes, bytes calldata data) external { + function collect(address serviceProvider, IGraphPayments.PaymentTypes, bytes calldata data) external returns (uint256) { uint256 amount = abi.decode(data, (uint256)); _releaseStake(serviceProvider, 0); _lockStake(serviceProvider, amount * STAKE_TO_FEES_RATIO, block.timestamp + LOCK_DURATION); diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol index ad5308e33..5d49f8873 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol @@ -29,7 +29,7 @@ contract DataServiceImpPausable is DataServicePausable { function stopService(address serviceProvider, bytes calldata data) external {} - function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external returns (uint256) {} function slash(address serviceProvider, bytes calldata data) external {} diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol index 14b23bc9c..5b55d0866 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol @@ -23,7 +23,7 @@ contract DataServiceImpPausableUpgradeable is DataServicePausableUpgradeable { function stopService(address serviceProvider, bytes calldata data) external {} - function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external {} + function collect(address serviceProvider, IGraphPayments.PaymentTypes feeType, bytes calldata data) external returns (uint256) {} function slash(address serviceProvider, bytes calldata data) external {} diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 27fdefd2f..ab0e02dc5 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -261,6 +261,7 @@ contract SubgraphService is onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused + returns (uint256) { uint256 paymentCollected = 0; @@ -273,6 +274,7 @@ contract SubgraphService is } emit ServicePaymentCollected(indexer, paymentType, paymentCollected); + return paymentCollected; } /** @@ -367,15 +369,12 @@ contract SubgraphService is } /** - * @notice See {ISubgraphService.setPaymentCuts} + * @notice See {ISubgraphService.setCurationCut} */ - function setPaymentCuts( - IGraphPayments.PaymentTypes paymentType, - uint128 serviceCut, - uint128 curationCut - ) external override onlyOwner { - paymentCuts[paymentType] = PaymentCuts(serviceCut, curationCut); - emit PaymentCutsSet(paymentType, serviceCut, curationCut); + function setCurationCut(uint256 curationCut) external override onlyOwner { + require(PPMMath.isValidPPM(curationCut), SubgraphServiceInvalidCurationCut(curationCut)); + curationFeesCut = curationCut; + emit CurationCutSet(curationCut); } /** @@ -512,34 +511,28 @@ contract SubgraphService is // release expired stake claims _releaseStake(_indexer, 0); - // Collect from GraphPayments - PaymentCuts memory queryFeePaymentCuts = _getQueryFeePaymentCuts(subgraphDeploymentId); - uint256 totalCut = queryFeePaymentCuts.serviceCut + queryFeePaymentCuts.curationCut; - + // Collect from GraphPayments - only curators cut is sent back to the subgraph service uint256 balanceBefore = _graphToken().balanceOf(address(this)); + + uint256 curationCut = _curation().isCurated(subgraphDeploymentId) ? curationFeesCut : 0; uint256 tokensCollected = _tapCollector().collect( IGraphPayments.PaymentTypes.QueryFee, - abi.encode(signedRav, totalCut) + abi.encode(signedRav, curationCut) ); - uint256 tokensDataService = tokensCollected.mulPPM(totalCut); + uint256 tokensCurators = tokensCollected.mulPPM(curationCut); + uint256 balanceAfter = _graphToken().balanceOf(address(this)); require( - balanceBefore + tokensDataService == balanceAfter, - SubgraphServiceInconsistentCollection(balanceBefore, balanceAfter, tokensDataService) + balanceBefore + tokensCurators == balanceAfter, + SubgraphServiceInconsistentCollection(balanceBefore, balanceAfter, tokensCurators) ); - uint256 tokensCurators = 0; - uint256 tokensSubgraphService = 0; if (tokensCollected > 0) { // lock stake as economic security for fees uint256 tokensToLock = tokensCollected * stakeToFeesRatio; uint256 unlockTimestamp = block.timestamp + _disputeManager().getDisputePeriod(); _lockStake(_indexer, tokensToLock, unlockTimestamp); - // calculate service and curator cuts - tokensCurators = tokensCollected.mulPPMRoundUp(queryFeePaymentCuts.curationCut); - tokensSubgraphService = tokensDataService - tokensCurators; - if (tokensCurators > 0) { // curation collection changes subgraph signal so we take rewards snapshot _graphRewardsManager().onSubgraphSignalUpdate(subgraphDeploymentId); @@ -550,23 +543,7 @@ contract SubgraphService is } } - emit QueryFeesCollected(_indexer, tokensCollected, tokensCurators, tokensSubgraphService); + emit QueryFeesCollected(_indexer, tokensCollected, tokensCurators); return tokensCollected; } - - /** - * @notice Gets the payment cuts for query fees - * Checks if the subgraph is curated and adjusts the curation cut accordingly - * @param _subgraphDeploymentId The subgraph deployment id - */ - function _getQueryFeePaymentCuts(bytes32 _subgraphDeploymentId) private view returns (PaymentCuts memory) { - PaymentCuts memory queryFeePaymentCuts = paymentCuts[IGraphPayments.PaymentTypes.QueryFee]; - - // Only pay curation fees if the subgraph is curated - if (!_curation().isCurated(_subgraphDeploymentId)) { - queryFeePaymentCuts.curationCut = 0; - } - - return queryFeePaymentCuts; - } } diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 50e72b417..54de429f1 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; -import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; abstract contract SubgraphServiceV1Storage { @@ -11,6 +10,6 @@ abstract contract SubgraphServiceV1Storage { ///@notice Multiplier for how many tokens back collected query fees uint256 public stakeToFeesRatio; - /// @notice The fees cut taken by the subgraph service - mapping(IGraphPayments.PaymentTypes paymentType => ISubgraphService.PaymentCuts paymentCuts) public paymentCuts; + /// @notice The cut curators take from query fee payments + uint256 public curationFeesCut; } diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 4cceee6b0..f03bd0b49 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -26,27 +26,13 @@ interface ISubgraphService is IDataServiceFees { string geoHash; } - /// @notice Payment cut definitions for each payment type - struct PaymentCuts { - // The cut the service provider takes from the payment - uint128 serviceCut; - // The cut curators take from the payment - uint128 curationCut; - } - /** * @notice Emitted when a subgraph service collects query fees from Graph Payments * @param serviceProvider The address of the service provider * @param tokensCollected The amount of tokens collected * @param tokensCurators The amount of tokens curators receive - * @param tokensSubgraphService The amount of tokens the subgraph service receives */ - event QueryFeesCollected( - address indexed serviceProvider, - uint256 tokensCollected, - uint256 tokensCurators, - uint256 tokensSubgraphService - ); + event QueryFeesCollected(address indexed serviceProvider, uint256 tokensCollected, uint256 tokensCurators); /** * @notice Emitted when the stake to fees ratio is set. @@ -55,12 +41,16 @@ interface ISubgraphService is IDataServiceFees { event StakeToFeesRatioSet(uint256 ratio); /** - * @notice Emmited when payment cuts are set for a payment type - * @param paymentType The payment type - * @param serviceCut The service cut for the payment type - * @param curationCut The curation cut for the payment type + * @notice Emmited when curator cuts are set + * @param curationCut The curation cut */ - event PaymentCutsSet(IGraphPayments.PaymentTypes paymentType, uint128 serviceCut, uint128 curationCut); + event CurationCutSet(uint256 curationCut); + + /** + * Thrown when trying to set a curation cut that is not a valid PPM value + * @param curationCut The curation cut value + */ + error SubgraphServiceInvalidCurationCut(uint256 curationCut); /** * @notice Thrown when an indexer tries to register with an empty URL @@ -89,9 +79,9 @@ interface ISubgraphService is IDataServiceFees { * from Graph Payments * @param balanceBefore The contract GRT balance before the collection * @param balanceAfter The contract GRT balance after the collection - * @param tokensCollected The amount of tokens collected + * @param tokensDataService The amount of tokens sent to the subgraph service */ - error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensCollected); + error SubgraphServiceInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokensDataService); /** * @notice @notice Thrown when the service provider in the RAV does not match the expected indexer. @@ -175,13 +165,11 @@ interface ISubgraphService is IDataServiceFees { function setMaxPOIStaleness(uint256 maxPOIStaleness) external; /** - * @notice Sets the payment cuts for a payment type - * @dev Emits a {PaymentCutsSet} event - * @param paymentType The payment type - * @param serviceCut The service cut for the payment type + * @notice Sets the curators payment cut for query fees + * @dev Emits a {CuratorCutSet} event * @param curationCut The curation cut for the payment type */ - function setPaymentCuts(IGraphPayments.PaymentTypes paymentType, uint128 serviceCut, uint128 curationCut) external; + function setCurationCut(uint256 curationCut) external; /** * @notice Sets the rewards destination for an indexer to receive indexing rewards diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 5e1322de3..1ebcf6683 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -188,7 +188,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { resetPrank(users.deployer); subgraphService.setStakeToFeesRatio(stakeToFeesRatio); subgraphService.setMaxPOIStaleness(maxPOIStaleness); - subgraphService.setPaymentCuts(IGraphPayments.PaymentTypes.QueryFee, serviceCut, curationCut); + subgraphService.setCurationCut(curationCut); } function unpauseProtocol() private { diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index b9f2fbcd1..e8292de45 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -24,10 +24,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { * HELPERS */ - function _getQueryFeeEncodedData( - address indexer, - uint128 tokens - ) private view returns (bytes memory) { + function _getQueryFeeEncodedData(address indexer, uint128 tokens) private view returns (bytes memory) { ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(indexer, tokens); bytes32 messageHash = tapCollector.encodeRAV(rav); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, messageHash); @@ -36,19 +33,23 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { return abi.encode(signedRAV); } - function _getRAV(address indexer, uint128 tokens) private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { - return ITAPCollector.ReceiptAggregateVoucher({ - dataService: address(subgraphService), - serviceProvider: indexer, - timestampNs: 0, - valueAggregate: tokens, - metadata: abi.encode(allocationID) - }); + function _getRAV( + address indexer, + uint128 tokens + ) private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { + return + ITAPCollector.ReceiptAggregateVoucher({ + dataService: address(subgraphService), + serviceProvider: indexer, + timestampNs: 0, + valueAggregate: tokens, + metadata: abi.encode(allocationID) + }); } - function _approveCollector(uint128 tokens) private { + function _approveCollector(uint256 tokens) private { address msgSender; - (, msgSender,) = vm.readCallers(); + (, msgSender, ) = vm.readCallers(); resetPrank(signer); mint(signer, tokens); escrow.approveCollector(address(tapCollector), tokens); @@ -72,56 +73,84 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { */ function testCollect_QueryFees( - uint256 tokens, + uint256 tokensAllocated, uint256 tokensPayment - ) public useIndexer useAllocation(tokens) { - vm.assume(tokens > minimumProvisionTokens * stakeToFeesRatio); - uint256 maxTokensPayment = tokens / stakeToFeesRatio > type(uint128).max ? type(uint128).max : tokens / stakeToFeesRatio; + ) public useIndexer useAllocation(tokensAllocated) { + vm.assume(tokensAllocated > minimumProvisionTokens * stakeToFeesRatio); + uint256 maxTokensPayment = tokensAllocated / stakeToFeesRatio > type(uint128).max + ? type(uint128).max + : tokensAllocated / stakeToFeesRatio; tokensPayment = bound(tokensPayment, minimumProvisionTokens, maxTokensPayment); - uint128 tokensPayment128 = uint128(tokensPayment); - IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; - bytes memory data = _getQueryFeeEncodedData(users.indexer, tokensPayment128); - + + _approveCollector(tokensPayment); + uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - - _approveCollector(tokensPayment128); - subgraphService.collect(users.indexer, paymentType, data); + + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokensPayment)); + uint256 tokensCollected = subgraphService.collect(users.indexer, IGraphPayments.PaymentTypes.QueryFee, data); uint256 indexerBalance = token.balanceOf(users.indexer); - uint256 tokensProtocol = tokensPayment128.mulPPM(protocolPaymentCut); - uint256 curationTokens = tokensPayment128.mulPPMRoundUp(curationCut); - uint256 dataServiceTokens = tokensPayment128.mulPPM(serviceCut + curationCut) - curationTokens; + uint256 tokensProtocol = tokensCollected.mulPPM(protocolPaymentCut); + uint256 curationTokens = tokensCollected.mulPPM(curationCut); - uint256 expectedIndexerTokensPayment = tokensPayment128 - tokensProtocol - dataServiceTokens - curationTokens; + uint256 expectedIndexerTokensPayment = tokensCollected - tokensProtocol - curationTokens; assertEq(indexerBalance, indexerPreviousBalance + expectedIndexerTokensPayment); } + function testCollect_MultipleQueryFees( + uint256 tokensAllocated, + uint256 numPayments + ) public useIndexer useAllocation(tokensAllocated) { + vm.assume(tokensAllocated > minimumProvisionTokens * stakeToFeesRatio); + numPayments = bound(numPayments, 1, 10); + uint256 tokensPayment = tokensAllocated / stakeToFeesRatio / numPayments; + + _approveCollector(tokensAllocated); + + uint256 accTokensPayment = 0; + for (uint i = 0; i < numPayments; i++) { + accTokensPayment = accTokensPayment + tokensPayment; + uint256 indexerPreviousBalance = token.balanceOf(users.indexer); + + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(accTokensPayment)); + uint256 tokensCollected = subgraphService.collect( + users.indexer, + IGraphPayments.PaymentTypes.QueryFee, + data + ); + + uint256 indexerBalance = token.balanceOf(users.indexer); + uint256 tokensProtocol = tokensCollected.mulPPM(protocolPaymentCut); + uint256 curationTokens = tokensCollected.mulPPM(curationCut); + + uint256 expectedIndexerTokensPayment = tokensCollected - tokensProtocol - curationTokens; + assertEq(indexerBalance, indexerPreviousBalance + expectedIndexerTokensPayment); + } + } + function testCollect_IndexingRewards(uint256 tokens) public useIndexer useAllocation(tokens) { _collectIndexingRewards(users.indexer, allocationID, tokens); } - function testCollect_RevertWhen_InvalidPayment( - uint256 tokens - ) public useIndexer useAllocation(tokens) { + function testCollect_RevertWhen_InvalidPayment(uint256 tokens) public useIndexer useAllocation(tokens) { IGraphPayments.PaymentTypes invalidPaymentType = IGraphPayments.PaymentTypes.IndexingFee; - vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceInvalidPaymentType.selector, - invalidPaymentType - )); + vm.expectRevert( + abi.encodeWithSelector(ISubgraphService.SubgraphServiceInvalidPaymentType.selector, invalidPaymentType) + ); subgraphService.collect(users.indexer, invalidPaymentType, ""); } - function testCollect_RevertWhen_NotAuthorized( - uint256 tokens - ) public useIndexer useAllocation(tokens) { + function testCollect_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); resetPrank(users.operator); - vm.expectRevert(abi.encodeWithSelector( - ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer - )); + vm.expectRevert( + abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + ) + ); subgraphService.collect(users.indexer, paymentType, data); } @@ -133,11 +162,13 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { address newIndexer = makeAddr("newIndexer"); _createAndStartAllocation(newIndexer, tokens); bytes memory data = _getQueryFeeEncodedData(newIndexer, uint128(tokens)); - vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, - newIndexer, - allocationID - )); + vm.expectRevert( + abi.encodeWithSelector( + ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, + newIndexer, + allocationID + ) + ); subgraphService.collect(newIndexer, paymentType, data); } @@ -149,11 +180,9 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { address newIndexer = makeAddr("newIndexer"); _createAndStartAllocation(newIndexer, tokens); bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); - vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceIndexerMismatch.selector, - users.indexer, - newIndexer - )); + vm.expectRevert( + abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerMismatch.selector, users.indexer, newIndexer) + ); subgraphService.collect(newIndexer, paymentType, data); } @@ -166,11 +195,9 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { _createAndStartAllocation(newIndexer, tokens); bytes memory data = abi.encode(allocationID, bytes32("POI1")); // Attempt to collect from other indexer's allocation - vm.expectRevert(abi.encodeWithSelector( - AllocationManager.AllocationManagerNotAuthorized.selector, - newIndexer, - allocationID - )); + vm.expectRevert( + abi.encodeWithSelector(AllocationManager.AllocationManagerNotAuthorized.selector, newIndexer, allocationID) + ); subgraphService.collect(newIndexer, paymentType, data); } } diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index e35659062..e533fd549 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -14,8 +14,7 @@ abstract contract Constants { uint32 internal constant delegationRatio = 16; uint256 public constant stakeToFeesRatio = 2; uint256 public constant maxPOIStaleness = 28 days; - uint128 public constant serviceCut = 10000; - uint128 public constant curationCut = 10000; + uint256 public constant curationCut = 10000; // Staking uint64 internal constant MAX_THAWING_PERIOD = 28 days; // GraphEscrow parameters From 0a9fe158f84a3a45b3029c97d9e75e15c2926993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 21 Aug 2024 15:09:54 -0300 Subject: [PATCH 169/277] fix: prevent provisions from being overwritten if they exist (OZ H-05) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../internal/IHorizonStakingMain.sol | 5 +++++ .../contracts/staking/HorizonStaking.sol | 1 + .../test/staking/provision/provision.t.sol | 20 ++++++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 25c5f85aa..e296f88e5 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -352,6 +352,11 @@ interface IHorizonStakingMain { */ error HorizonStakingInvalidThawingPeriod(uint64 thawingPeriod, uint64 maxThawingPeriod); + /** + * @notice Thrown when attempting to create a provision for a data service that already has a provision. + */ + error HorizonStakingProvisionAlreadyExists(); + // -- Errors: stake -- /** diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 4d3349b7a..45ce7c8cb 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -606,6 +606,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _thawingPeriod <= _maxThawingPeriod, HorizonStakingInvalidThawingPeriod(_thawingPeriod, _maxThawingPeriod) ); + require(_provisions[_serviceProvider][_verifier].createdAt == 0, HorizonStakingProvisionAlreadyExists()); uint256 tokensIdle = _getIdleStake(_serviceProvider); require(_tokens <= tokensIdle, HorizonStakingInsufficientIdleStake(_tokens, tokensIdle)); diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index fc941ec7f..3394460fb 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -6,7 +6,6 @@ import "forge-std/Test.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingProvisionTest is HorizonStakingTest { - /* * TESTS */ @@ -68,6 +67,21 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { staking.provision(users.indexer, subgraphDataServiceAddress, provisionTokens, 0, 0); } + function testProvision_RevertWhen_AlreadyExists( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount / 2, maxVerifierCut, thawingPeriod) { + resetPrank(users.indexer); + + token.approve(address(staking), amount / 2); + staking.stake(amount / 2); + + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingProvisionAlreadyExists()"); + vm.expectRevert(expectedError); + staking.provision(users.indexer, subgraphDataServiceAddress, amount / 2, maxVerifierCut, thawingPeriod); + } + function testProvision_OperatorAddTokensToProvision( uint256 amount, uint32 maxVerifierCut, @@ -94,7 +108,7 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingNotAuthorized(address,address,address)", + "HorizonStakingNotAuthorized(address,address,address)", users.operator, users.indexer, subgraphDataServiceAddress @@ -102,4 +116,4 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.provision(users.indexer, subgraphDataServiceAddress, amount, maxVerifierCut, thawingPeriod); } -} \ No newline at end of file +} From ab8f39b840035a651afdf938744e6a9c836c9182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 21 Aug 2024 15:49:24 -0300 Subject: [PATCH 170/277] fix: div by zero when delegating to a pool where all tokens are thawing (OZ H-06) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/staking/HorizonStaking.sol | 4 ++- .../staking/HorizonStakingExtension.sol | 4 ++- .../horizon/test/staking/HorizonStaking.t.sol | 2 +- .../test/staking/delegation/delegate.t.sol | 15 ++++++++++ .../test/staking/transfer-tools/ttools.t.sol | 28 ++++++++++++++++++- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 45ce7c8cb..d0c227157 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -720,7 +720,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { ); // Calculate shares to issue - uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); + uint256 shares = (pool.tokens == 0 || pool.tokens == pool.tokensThawing) + ? _tokens + : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); require(shares != 0 && shares >= _minSharesOut, HorizonStakingSlippageProtection(shares, _minSharesOut)); pool.tokens = pool.tokens + _tokens; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 8f7ab8449..38987944d 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -358,7 +358,9 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon } // Calculate shares to issue (without applying any delegation tax) - uint256 shares = (pool.tokens == 0) ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); + uint256 shares = (pool.tokens == 0 || pool.tokens == pool.tokensThawing) + ? _tokens + : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); if (shares == 0 || _tokens < MINIMUM_DELEGATION) { // If no shares would be issued (probably a rounding issue or attack), diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index bf0106fca..75d23948d 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -143,7 +143,7 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { stakingBalance: token.balanceOf(address(staking)) }); - uint256 calcShares = (beforeData.pool.tokens == 0) + uint256 calcShares = (beforeData.pool.tokens == 0 || beforeData.pool.tokens == beforeData.pool.tokensThawing) ? tokens : ((tokens * beforeData.pool.shares) / (beforeData.pool.tokens - beforeData.pool.tokensThawing)); diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 939893794..79443f96c 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -37,6 +37,21 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); } + function testDelegate_Tokens_WhenAllThawing( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 1 days) { + delegationAmount = bound(delegationAmount, 1 ether, MAX_STAKING_TOKENS); + + vm.startPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); + + Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); + + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); + } + function testDelegate_RevertWhen_ZeroTokens(uint256 amount) public useIndexer useProvision(amount, 0, 0) { vm.startPrank(users.delegator); bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); diff --git a/packages/horizon/test/staking/transfer-tools/ttools.t.sol b/packages/horizon/test/staking/transfer-tools/ttools.t.sol index 71bf2bb3e..28bc11264 100644 --- a/packages/horizon/test/staking/transfer-tools/ttools.t.sol +++ b/packages/horizon/test/staking/transfer-tools/ttools.t.sol @@ -129,6 +129,32 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { ); _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); } + function testOnTransfer_ReceiveDelegation_WhenAllThawing(uint256 amountReceived, uint256 amountDelegated) public { + amountReceived = bound(amountReceived, 1 ether, MAX_STAKING_TOKENS); + amountDelegated = bound(amountDelegated, 1 ether, MAX_STAKING_TOKENS); + + // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 + resetPrank(users.indexer); + _createProvision(subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); + + resetPrank(users.delegator); + _delegateLegacy(users.indexer, amountDelegated); + + // send amount to staking contract - this should be done by the bridge + resetPrank(users.delegator); + token.transfer(address(staking), amountReceived); + + // thaw all delegation before receiving new delegation from L1 + resetPrank(users.delegator); + _undelegateLegacy(users.indexer, amountDelegated); + + resetPrank(graphTokenGatewayAddress); + bytes memory data = abi.encode( + uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), + abi.encode(users.indexer, users.delegator) + ); + _onTokenTransfer_ReceiveDelegation(counterpartStaking, amountReceived, data); + } /** * HELPERS @@ -153,7 +179,7 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { ); uint256 beforeDelegatorBalance = token.balanceOf(delegator); uint256 beforeStakingBalance = token.balanceOf(address(staking)); - uint256 calcShares = (beforePool.tokens == 0) + uint256 calcShares = (beforePool.tokens == 0 || beforePool.tokens == beforePool.tokensThawing) ? tokens : ((tokens * beforePool.shares) / (beforePool.tokens - beforePool.tokensThawing)); From 61bf0eefb9c8bf1f468902ad97383a835c12c910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 22 Aug 2024 11:45:55 -0300 Subject: [PATCH 171/277] fix: remove white space from typehash calculation (OZ H-07) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/horizon/contracts/payments/collectors/TAPCollector.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index 77e086022..c8b52a188 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -24,7 +24,7 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { /// @notice The EIP712 typehash for the ReceiptAggregateVoucher struct bytes32 private constant EIP712_RAV_TYPEHASH = keccak256( - "ReceiptAggregateVoucher(address dataService, address serviceProvider,uint64 timestampNs,uint128 valueAggregate,bytes metadata)" + "ReceiptAggregateVoucher(address dataService,address serviceProvider,uint64 timestampNs,uint128 valueAggregate,bytes metadata)" ); /// @notice Tracks the amount of tokens already collected by a data service from a payer to a receiver From 11b7d443ef8056aba6f43b2b7f6305373d921a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 14:08:41 -0300 Subject: [PATCH 172/277] fix: include rav metadata in signature verification (OZ H-08) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../horizon/contracts/payments/collectors/TAPCollector.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index c8b52a188..4ba835ace 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -120,7 +120,8 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { _rav.dataService, _rav.serviceProvider, _rav.timestampNs, - _rav.valueAggregate + _rav.valueAggregate, + _rav.metadata ) ) ); From 03ce865cc9e005ee85ff889eae86b1033c19bd11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 15:40:49 -0300 Subject: [PATCH 173/277] fix: wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/SubgraphService.sol | 59 ++++++++++++------ .../contracts/interfaces/ISubgraphService.sol | 36 +++++++++++ .../contracts/libraries/Allocation.sol | 12 ++++ .../contracts/utilities/AllocationManager.sol | 45 +++++--------- .../subgraphService/allocate/resize.t.sol | 3 +- .../test/subgraphService/allocate/stop.t.sol | 61 ++++++++++++------- .../subgraphService/collect/collect.t.sol | 10 ++- 7 files changed, 154 insertions(+), 72 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index ab0e02dc5..d9a9ca45c 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -222,7 +222,7 @@ contract SubgraphService is ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { address allocationId = abi.decode(data, (address)); require( - allocations[allocationId].indexer == indexer, + allocations.get(allocationId).indexer == indexer, SubgraphServiceAllocationNotAuthorized(indexer, allocationId) ); _closeAllocation(allocationId); @@ -266,9 +266,19 @@ contract SubgraphService is uint256 paymentCollected = 0; if (paymentType == IGraphPayments.PaymentTypes.QueryFee) { - paymentCollected = _collectQueryFees(indexer, data); + ITAPCollector.SignedRAV memory signedRav = abi.decode(data, (ITAPCollector.SignedRAV)); + require( + signedRav.rav.serviceProvider == indexer, + SubgraphServiceIndexerMismatch(signedRav.rav.serviceProvider, indexer) + ); + paymentCollected = _collectQueryFees(signedRav); } else if (paymentType == IGraphPayments.PaymentTypes.IndexingRewards) { - paymentCollected = _collectIndexingRewards(indexer, data); + (address allocationId, bytes32 poi) = abi.decode(data, (address, bytes32)); + require( + allocations.get(allocationId).indexer == indexer, + SubgraphServiceAllocationNotAuthorized(indexer, allocationId) + ); + paymentCollected = _collectIndexingRewards(allocationId, poi); } else { revert SubgraphServiceInvalidPaymentType(paymentType); } @@ -297,6 +307,19 @@ contract SubgraphService is emit ServiceProviderSlashed(indexer, tokens); } + /** + * @notice See {ISubgraphService.closeStaleAllocation} + */ + function closeStaleAllocation(address allocationId) external override { + Allocation.State memory allocation = allocations.get(allocationId); + require( + allocation.isStale(maxPOIStaleness), + SubgraphServiceAllocationNotStale(allocationId, allocation.lastPOIPresentedAt) + ); + require(!allocation.isAltruistic(), SubgraphServiceAllocationIsAltruistic(allocationId)); + _closeAllocation(allocationId); + } + /** * @notice See {ISubgraphService.resizeAllocation} */ @@ -311,7 +334,11 @@ contract SubgraphService is onlyRegisteredIndexer(indexer) whenNotPaused { - _resizeAllocation(indexer, allocationId, tokens, delegationRatio); + require( + allocations.get(allocationId).indexer == indexer, + SubgraphServiceAllocationNotAuthorized(indexer, allocationId) + ); + _resizeAllocation(allocationId, tokens, delegationRatio); } /** @@ -493,23 +520,19 @@ contract SubgraphService is * Emits a {StakeClaimLocked} event. * Emits a {QueryFeesCollected} event. * - * @param _indexer The address of the indexer - * @param _data Encoded data containing a signed RAV + * @param _signedRav Signed RAV */ - function _collectQueryFees(address _indexer, bytes memory _data) private returns (uint256 feesCollected) { - ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); - address indexer = signedRav.rav.serviceProvider; - require(_indexer == indexer, SubgraphServiceIndexerMismatch(indexer, _indexer)); - address allocationId = abi.decode(signedRav.rav.metadata, (address)); + function _collectQueryFees(ITAPCollector.SignedRAV memory _signedRav) private returns (uint256 feesCollected) { + address indexer = _signedRav.rav.serviceProvider; + address allocationId = abi.decode(_signedRav.rav.metadata, (address)); Allocation.State memory allocation = allocations.get(allocationId); - // Not strictly necessary: if an indexer collects another's voucher, they lock their stake with no gains. - // We include the check to guard against potential malicious payers deceiving the indexer. - require(allocation.indexer == _indexer, SubgraphServiceAllocationNotAuthorized(_indexer, allocationId)); + // Check RAV is consistent - RAV indexer must match the allocation's indexer + require(allocation.indexer == indexer, SubgraphServiceInvalidRAV(indexer, allocation.indexer)); bytes32 subgraphDeploymentId = allocation.subgraphDeploymentId; // release expired stake claims - _releaseStake(_indexer, 0); + _releaseStake(indexer, 0); // Collect from GraphPayments - only curators cut is sent back to the subgraph service uint256 balanceBefore = _graphToken().balanceOf(address(this)); @@ -517,7 +540,7 @@ contract SubgraphService is uint256 curationCut = _curation().isCurated(subgraphDeploymentId) ? curationFeesCut : 0; uint256 tokensCollected = _tapCollector().collect( IGraphPayments.PaymentTypes.QueryFee, - abi.encode(signedRav, curationCut) + abi.encode(_signedRav, curationCut) ); uint256 tokensCurators = tokensCollected.mulPPM(curationCut); @@ -531,7 +554,7 @@ contract SubgraphService is // lock stake as economic security for fees uint256 tokensToLock = tokensCollected * stakeToFeesRatio; uint256 unlockTimestamp = block.timestamp + _disputeManager().getDisputePeriod(); - _lockStake(_indexer, tokensToLock, unlockTimestamp); + _lockStake(indexer, tokensToLock, unlockTimestamp); if (tokensCurators > 0) { // curation collection changes subgraph signal so we take rewards snapshot @@ -543,7 +566,7 @@ contract SubgraphService is } } - emit QueryFeesCollected(_indexer, tokensCollected, tokensCurators); + emit QueryFeesCollected(indexer, tokensCollected, tokensCurators); return tokensCollected; } } diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index f03bd0b49..5e82c66ed 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -97,6 +97,26 @@ interface ISubgraphService is IDataServiceFees { */ error SubgraphServiceAllocationNotAuthorized(address indexer, address allocationId); + /** + * @notice Thrown when collecting a RAV where the RAV indexer is not the same as the allocation indexer + * @param ravIndexer The address of the RAV indexer + * @param allocationIndexer The address of the allocation indexer + */ + error SubgraphServiceInvalidRAV(address ravIndexer, address allocationIndexer); + + /** + * @notice Thrown when trying to force close an allocation that is not stale + * @param allocationId The id of the allocation + * @param lastPOIPresentedAt The timestamp when the last POI was presented + */ + error SubgraphServiceAllocationNotStale(address allocationId, uint256 lastPOIPresentedAt); + + /** + * @notice Thrown when trying to force close an altruistic allocation + * @param allocationId The id of the allocation + */ + error SubgraphServiceAllocationIsAltruistic(address allocationId); + /** * @notice Initialize the contract * @param minimumProvisionTokens The minimum amount of provisioned tokens required to create an allocation @@ -104,6 +124,22 @@ interface ISubgraphService is IDataServiceFees { */ function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external; + /** + * @notice Close a stale allocation + * @dev This function can be permissionlessly called when the allocation is stale. + * This ensures rewards for other allocations are not diluted by an inactive allocation + * + * Requirements: + * - Allocation must exist and be open + * - Allocation must be stale + * - Allocation cannot be altruistic + * + * Emits a {AllocationClosed} event. + * + * @param allocationId The id of the allocation + */ + function closeStaleAllocation(address allocationId) external; + /** * @notice Change the amount of tokens in an allocation * @dev Requirements: diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index 7511f360a..df3fe5f59 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; + /** * @title Allocation library * @notice A library to handle Allocations. @@ -164,6 +166,16 @@ library Allocation { return _get(self, allocationId); } + /** + * @notice Checks if an allocation is stale + * @param self The allocation + * @param staleThreshold The time in blocks to consider an allocation stale + */ + function isStale(State memory self, uint256 staleThreshold) internal view returns (bool) { + uint256 timeSinceLastPOI = block.number - Math.max(self.createdAt, self.lastPOIPresentedAt); + return self.isOpen() && timeSinceLastPOI <= staleThreshold; + } + /** * @notice Checks if an allocation exists * @param self The allocation diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 1ddb25f5e..fed133d03 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -152,13 +152,6 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca */ error AllocationManagerAllocationSameSize(address allocationId, uint256 tokens); - /** - * @notice Thrown when an indexer is not allocation owner - * @param allocationId The id of the allocation - * @param indexer The address of the indexer - */ - error AllocationManagerNotAuthorized(address indexer, address allocationId); - /** * @notice Initializes the contract and parent contracts */ @@ -257,43 +250,40 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * * Emits a {IndexingRewardsCollected} event. * - * @param _indexer The address of the indexer - * @param _data Encoded data containing: - * - address `allocationId`: The id of the allocation to collect rewards for - * - bytes32 `poi`: The POI being presented + * @param _allocationId The id of the allocation to collect rewards for + * @param _poi The POI being presented */ - function _collectIndexingRewards(address _indexer, bytes memory _data) internal returns (uint256) { - (address allocationId, bytes32 poi) = abi.decode(_data, (address, bytes32)); - - Allocation.State memory allocation = allocations.get(allocationId); - require(allocation.indexer == _indexer, AllocationManagerNotAuthorized(_indexer, allocationId)); - require(allocation.isOpen(), AllocationManagerAllocationClosed(allocationId)); + function _collectIndexingRewards(address _allocationId, bytes32 _poi) internal returns (uint256) { + Allocation.State memory allocation = allocations.get(_allocationId); + require(allocation.isOpen(), AllocationManagerAllocationClosed(_allocationId)); // Mint indexing rewards if all conditions are met uint256 timeSinceLastPOI = block.number - Math.max(allocation.createdAt, allocation.lastPOIPresentedAt); - uint256 tokensRewards = (timeSinceLastPOI <= maxPOIStaleness && poi != bytes32(0) && !allocation.isAltruistic()) - ? _graphRewardsManager().takeRewards(allocationId) + uint256 tokensRewards = (timeSinceLastPOI <= maxPOIStaleness && + _poi != bytes32(0) && + !allocation.isAltruistic()) + ? _graphRewardsManager().takeRewards(_allocationId) : 0; // ... but we still take a snapshot to ensure the rewards are not accumulated for the next valid POI allocations.snapshotRewards( - allocationId, + _allocationId, _graphRewardsManager().onSubgraphAllocationUpdate(allocation.subgraphDeploymentId) ); - allocations.presentPOI(allocationId); + allocations.presentPOI(_allocationId); // Any pending rewards should have been collected now - allocations.clearPendingRewards(allocationId); + allocations.clearPendingRewards(_allocationId); if (tokensRewards == 0) { emit IndexingRewardsCollected( allocation.indexer, - allocationId, + _allocationId, allocation.subgraphDeploymentId, 0, 0, 0, - poi + _poi ); return tokensRewards; } @@ -322,12 +312,12 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca emit IndexingRewardsCollected( allocation.indexer, - allocationId, + _allocationId, allocation.subgraphDeploymentId, tokensRewards, tokensIndexerRewards, tokensDelegationRewards, - poi + _poi ); return tokensRewards; @@ -346,19 +336,16 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * * Emits a {AllocationResized} event. * - * @param _indexer The address of the indexer * @param _allocationId The id of the allocation to be resized * @param _tokens The new amount of tokens to allocate * @param _delegationRatio The delegation ratio to consider when locking tokens */ function _resizeAllocation( - address _indexer, address _allocationId, uint256 _tokens, uint32 _delegationRatio ) internal returns (Allocation.State memory) { Allocation.State memory allocation = allocations.get(_allocationId); - require(allocation.indexer == _indexer, AllocationManagerNotAuthorized(_indexer, _allocationId)); require(allocation.isOpen(), AllocationManagerAllocationClosed(_allocationId)); require(_tokens != allocation.tokens, AllocationManagerAllocationSameSize(_allocationId, _tokens)); diff --git a/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol b/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol index 9fdd327dc..a2d8ef4a7 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol @@ -6,6 +6,7 @@ import "forge-std/Test.sol"; import { Allocation } from "../../../contracts/libraries/Allocation.sol"; import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; contract SubgraphServiceAllocateResizeTest is SubgraphServiceTest { @@ -100,7 +101,7 @@ contract SubgraphServiceAllocateResizeTest is SubgraphServiceTest { address newIndexer = makeAddr("newIndexer"); _createAndStartAllocation(newIndexer, tokens); vm.expectRevert(abi.encodeWithSelector( - AllocationManager.AllocationManagerNotAuthorized.selector, + ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, newIndexer, allocationID )); diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index 6e53ab886..725531c72 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -14,7 +14,6 @@ import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation. import { SubgraphServiceTest } from "../SubgraphService.t.sol"; contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { - /* * Helpers */ @@ -27,49 +26,69 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { _stopAllocation(users.indexer, allocationID); } - function testStop_RevertWhen_IndexerIsNotTheAllocationOwner(uint256 tokens) public useIndexer useAllocation(tokens) { + function testStop_RevertWhen_IndexerIsNotTheAllocationOwner( + uint256 tokens + ) public useIndexer useAllocation(tokens) { // Setup new indexer address newIndexer = makeAddr("newIndexer"); _createAndStartAllocation(newIndexer, tokens); // Attempt to close other indexer's allocation bytes memory data = abi.encode(allocationID); - vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, - newIndexer, - allocationID - )); + vm.expectRevert( + abi.encodeWithSelector( + ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, + newIndexer, + allocationID + ) + ); subgraphService.stopService(newIndexer, data); } function testStop_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { resetPrank(users.operator); bytes memory data = abi.encode(allocationID); - vm.expectRevert(abi.encodeWithSelector( - ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer - )); + vm.expectRevert( + abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + ) + ); subgraphService.stopService(users.indexer, data); } function testStop_RevertWhen_NotRegistered() public useIndexer { bytes memory data = abi.encode(allocationID); - vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, - users.indexer - )); + vm.expectRevert( + abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, users.indexer) + ); subgraphService.stopService(users.indexer, data); } function testStop_RevertWhen_NotOpen(uint256 tokens) public useIndexer useAllocation(tokens) { bytes memory data = abi.encode(allocationID); subgraphService.stopService(users.indexer, data); - vm.expectRevert(abi.encodeWithSelector( - Allocation.AllocationClosed.selector, - allocationID, - block.timestamp - )); + vm.expectRevert(abi.encodeWithSelector(Allocation.AllocationClosed.selector, allocationID, block.timestamp)); subgraphService.stopService(users.indexer, data); } + + function testCloseStaleAllocation( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + address permissionlessBob = makeAddr("permissionlessBob"); + + vm.warp(maxPOIStaleness + 1); + + resetPrank(permissionlessBob); + vm.expectEmitted( + abi.encodeWithSelector( + ISubgraphService.SubgraphServiceAllocationClosed.selector, + allocationID + ) + ); + subgraphService.closeStaleAllocation(allocationID); + + assertEq(); + } } diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index e8292de45..07294b25a 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -161,12 +161,16 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { // Setup new indexer address newIndexer = makeAddr("newIndexer"); _createAndStartAllocation(newIndexer, tokens); + + // This data is for user.indexer allocationId bytes memory data = _getQueryFeeEncodedData(newIndexer, uint128(tokens)); + + resetPrank(newIndexer); vm.expectRevert( abi.encodeWithSelector( - ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, + ISubgraphService.SubgraphServiceInvalidRAV.selector, newIndexer, - allocationID + users.indexer ) ); subgraphService.collect(newIndexer, paymentType, data); @@ -196,7 +200,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { bytes memory data = abi.encode(allocationID, bytes32("POI1")); // Attempt to collect from other indexer's allocation vm.expectRevert( - abi.encodeWithSelector(AllocationManager.AllocationManagerNotAuthorized.selector, newIndexer, allocationID) + abi.encodeWithSelector(ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, newIndexer, allocationID) ); subgraphService.collect(newIndexer, paymentType, data); } From dd6a0071bc78b3cebe1816039491b607158ed699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 15:44:45 -0300 Subject: [PATCH 174/277] fix: add fn to allow force closing stale allocations (OZ H-09) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../test/subgraphService/allocate/stop.t.sol | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index 725531c72..a183f0790 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -81,14 +81,6 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { vm.warp(maxPOIStaleness + 1); resetPrank(permissionlessBob); - vm.expectEmitted( - abi.encodeWithSelector( - ISubgraphService.SubgraphServiceAllocationClosed.selector, - allocationID - ) - ); subgraphService.closeStaleAllocation(allocationID); - - assertEq(); } } From 7b7cff21fc53a19c7628531ba5c19eaf04eb3adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 16:21:19 -0300 Subject: [PATCH 175/277] fix: timestamp instead of block number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../subgraph-service/contracts/libraries/Allocation.sol | 4 ++-- .../contracts/utilities/AllocationManager.sol | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index df3fe5f59..d8f08d6d6 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -172,8 +172,8 @@ library Allocation { * @param staleThreshold The time in blocks to consider an allocation stale */ function isStale(State memory self, uint256 staleThreshold) internal view returns (bool) { - uint256 timeSinceLastPOI = block.number - Math.max(self.createdAt, self.lastPOIPresentedAt); - return self.isOpen() && timeSinceLastPOI <= staleThreshold; + uint256 timeSinceLastPOI = block.timestamp - Math.max(self.createdAt, self.lastPOIPresentedAt); + return self.isOpen() && timeSinceLastPOI > staleThreshold; } /** diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index fed133d03..f386c4371 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -6,7 +6,6 @@ import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGra import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/GraphDirectory.sol"; import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; -import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; import { Allocation } from "../libraries/Allocation.sol"; @@ -258,10 +257,9 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca require(allocation.isOpen(), AllocationManagerAllocationClosed(_allocationId)); // Mint indexing rewards if all conditions are met - uint256 timeSinceLastPOI = block.number - Math.max(allocation.createdAt, allocation.lastPOIPresentedAt); - uint256 tokensRewards = (timeSinceLastPOI <= maxPOIStaleness && - _poi != bytes32(0) && - !allocation.isAltruistic()) + uint256 tokensRewards = (!allocation.isStale(maxPOIStaleness) && + !allocation.isAltruistic() && + _poi != bytes32(0)) ? _graphRewardsManager().takeRewards(_allocationId) : 0; From 36f911280b66ffbde0c4ac2c7fe0b354191c22ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 17:14:25 -0300 Subject: [PATCH 176/277] test: use skip instead of warp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../subgraph-service/test/subgraphService/allocate/stop.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol index a183f0790..fff5c457f 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol @@ -78,7 +78,7 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { ) public useIndexer useAllocation(tokens) { address permissionlessBob = makeAddr("permissionlessBob"); - vm.warp(maxPOIStaleness + 1); + skip(maxPOIStaleness + 1); resetPrank(permissionlessBob); subgraphService.closeStaleAllocation(allocationID); From 41eb02ba8171f573d7aaf7a6128c14f867f65e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 17:07:21 -0300 Subject: [PATCH 177/277] fix: max verifier tokens calculation when slashing (OZ H-11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/staking/HorizonStaking.sol | 22 +++++++++++++++++-- .../horizon/test/staking/slash/slash.t.sol | 22 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index d0c227157..5095b4f33 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -363,9 +363,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { require(tokensProvisionTotal != 0, HorizonStakingInsufficientTokens(tokensProvisionTotal, tokens)); uint256 tokensToSlash = MathUtils.min(tokens, tokensProvisionTotal); + + // Slash service provider first + // - A portion goes to verifier as reward + // - A portion gets burned uint256 providerTokensSlashed = MathUtils.min(prov.tokens, tokensToSlash); if (providerTokensSlashed > 0) { - uint256 maxVerifierTokens = prov.tokens.mulPPM(prov.maxVerifierCut); + // Pay verifier reward - must be within the maxVerifierCut percentage + uint256 maxVerifierTokens = providerTokensSlashed.mulPPM(prov.maxVerifierCut); require( maxVerifierTokens >= tokensVerifier, HorizonStakingTooManyTokens(tokensVerifier, maxVerifierTokens) @@ -374,32 +379,45 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _graphToken().pushTokens(verifierDestination, tokensVerifier); emit VerifierTokensSent(serviceProvider, verifier, verifierDestination, tokensVerifier); } + + // Burn remainder _graphToken().burnTokens(providerTokensSlashed - tokensVerifier); - uint256 provisionFractionSlashed = (providerTokensSlashed * FIXED_POINT_PRECISION) / prov.tokens; + + // Provision accounting // TODO check for rounding issues + uint256 provisionFractionSlashed = (providerTokensSlashed * FIXED_POINT_PRECISION) / prov.tokens; prov.tokensThawing = (prov.tokensThawing * (FIXED_POINT_PRECISION - provisionFractionSlashed)) / (FIXED_POINT_PRECISION); prov.tokens = prov.tokens - providerTokensSlashed; + + // Service provider accounting _serviceProviders[serviceProvider].tokensProvisioned = _serviceProviders[serviceProvider].tokensProvisioned - providerTokensSlashed; _serviceProviders[serviceProvider].tokensStaked = _serviceProviders[serviceProvider].tokensStaked - providerTokensSlashed; + emit ProvisionSlashed(serviceProvider, verifier, providerTokensSlashed); } + // Slash delegators if needed + // - Slashed delegation is entirely burned // Since tokensToSlash is already limited above, this subtraction will remain within pool.tokens. tokensToSlash = tokensToSlash - providerTokensSlashed; if (tokensToSlash > 0) { if (_delegationSlashingEnabled) { + // Burn tokens _graphToken().burnTokens(tokensToSlash); + + // Delegation pool accounting uint256 delegationFractionSlashed = (tokensToSlash * FIXED_POINT_PRECISION) / pool.tokens; pool.tokens = pool.tokens - tokensToSlash; pool.tokensThawing = (pool.tokensThawing * (FIXED_POINT_PRECISION - delegationFractionSlashed)) / FIXED_POINT_PRECISION; + emit DelegationSlashed(serviceProvider, verifier, tokensToSlash); } else { emit DelegationSlashingSkipped(serviceProvider, verifier, tokensToSlash); diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 1644e336e..b535295fa 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -27,7 +27,6 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 slashTokens, uint256 verifierCutAmount ) public useIndexer useProvision(tokens, maxVerifierCut, 0) { - verifierCutAmount = bound(verifierCutAmount, 0, maxVerifierCut); slashTokens = bound(slashTokens, 1, tokens); uint256 maxVerifierTokens = (slashTokens * maxVerifierCut) / MAX_PPM; vm.assume(verifierCutAmount <= maxVerifierTokens); @@ -36,6 +35,27 @@ contract HorizonStakingSlashTest is HorizonStakingTest { _slash(users.indexer, subgraphDataServiceAddress, slashTokens, verifierCutAmount); } + function testSlash_Tokens_RevertWhen_TooManyVerifierTokens( + uint256 tokens, + uint32 maxVerifierCut, + uint256 slashTokens, + uint256 verifierCutAmount + ) public useIndexer useProvision(tokens, maxVerifierCut, 0) { + slashTokens = bound(slashTokens, 1, tokens); + uint256 maxVerifierTokens = (slashTokens * maxVerifierCut) / MAX_PPM; + vm.assume(verifierCutAmount > maxVerifierTokens); + + vm.startPrank(subgraphDataServiceAddress); + vm.assume(slashTokens > 0); + bytes memory expectedError = abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingTooManyTokens.selector, + verifierCutAmount, + maxVerifierTokens + ); + vm.expectRevert(expectedError); + staking.slash(users.indexer, slashTokens, verifierCutAmount, subgraphDataServiceAddress); + } + function testSlash_DelegationDisabled_SlashingOverProviderTokens( uint256 tokens, uint256 slashTokens, From b2bf0708662866226f7213814579902a70339593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 18:04:07 -0300 Subject: [PATCH 178/277] fix: consider tokens allocated to legacy allos as not idle (OZ H-10) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../horizon/contracts/staking/HorizonStaking.sol | 9 --------- .../contracts/staking/HorizonStakingBase.sol | 1 + .../allocation/HorizonStakingExtension.t.sol | 1 + .../horizon/test/staking/allocation/close.t.sol | 13 ++++++++----- .../horizon/test/staking/allocation/collect.t.sol | 6 +++--- 5 files changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 5095b4f33..b7f20bf43 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -537,15 +537,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { ServiceProviderInternal storage sp = _serviceProviders[serviceProvider]; uint256 stakedTokens = sp.tokensStaked; - // Check that the service provider's stake minus the tokens to unstake is sufficient - // to cover existing allocations - // TODO this is only needed until legacy allocations are closed, - // so we should remove it after the transition period - uint256 remainingTokens = stakedTokens - _tokens; - require( - remainingTokens >= sp.__DEPRECATED_tokensAllocated, - HorizonStakingInsufficientStakeForLegacyAllocations(remainingTokens, sp.__DEPRECATED_tokensAllocated) - ); // This is also only during the transition period: we need // to ensure tokens stay locked after closing legacy allocations. diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index eeac9f800..f62e593b1 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -260,6 +260,7 @@ abstract contract HorizonStakingBase is return _serviceProviders[_serviceProvider].tokensStaked - _serviceProviders[_serviceProvider].tokensProvisioned - + _serviceProviders[_serviceProvider].__DEPRECATED_tokensAllocated - _serviceProviders[_serviceProvider].__DEPRECATED_tokensLocked; } diff --git a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol index 19a42da2b..bf9524c43 100644 --- a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol +++ b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol @@ -77,6 +77,7 @@ contract HorizonStakingExtensionTest is HorizonStakingTest { uint256 serviceProviderSlot = 14; bytes32 serviceProviderBaseSlot = keccak256(abi.encode(_allocation.indexer, serviceProviderSlot)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 0), bytes32(tokens)); vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 1), bytes32(tokens)); uint256 subgraphsAllocationsSlot = 16; diff --git a/packages/horizon/test/staking/allocation/close.t.sol b/packages/horizon/test/staking/allocation/close.t.sol index d8524bb92..c7c2aff68 100644 --- a/packages/horizon/test/staking/allocation/close.t.sol +++ b/packages/horizon/test/staking/allocation/close.t.sol @@ -28,7 +28,7 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); // Stake should be updated with rewards - assertEq(staking.getStake(address(users.indexer)), tokens + ALLOCATIONS_REWARD_CUT); + assertEq(staking.getStake(address(users.indexer)), tokens * 2 + ALLOCATIONS_REWARD_CUT); } function testCloseAllocation_WithBeneficiaryAddress(uint256 tokens) public useIndexer { @@ -77,7 +77,7 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); // No rewards distributed - assertEq(staking.getStake(address(users.indexer)), tokens); + assertEq(staking.getStake(address(users.indexer)), tokens * 2); } function testCloseAllocation_RevertWhen_ZeroTokensNotAuthorized() public useIndexer { @@ -93,13 +93,16 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { } function testCloseAllocation_WithDelegation(uint256 tokens, uint256 delegationTokens, uint32 indexingRewardCut) public useIndexer { - tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + tokens = bound(tokens, 2, MAX_STAKING_TOKENS); delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); vm.assume(indexingRewardCut <= MAX_PPM); - _storeAllocation(tokens); + uint256 legacyAllocationTokens = tokens / 2; + uint256 provisionTokens = tokens - legacyAllocationTokens; + + _storeAllocation(legacyAllocationTokens); _storeMaxAllocationEpochs(); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); _storeDelegationPool(delegationTokens, indexingRewardCut, 0); // Skip 15 epochs diff --git a/packages/horizon/test/staking/allocation/collect.t.sol b/packages/horizon/test/staking/allocation/collect.t.sol index 43c3c67ca..3ea230a8b 100644 --- a/packages/horizon/test/staking/allocation/collect.t.sol +++ b/packages/horizon/test/staking/allocation/collect.t.sol @@ -84,7 +84,7 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { assertEq(staking.getStake(address(users.indexer)), 0); } - function testCollect_Tokens( + function testCollect_Tokenss( uint256 provisionTokens, uint256 allocationTokens, uint256 collectTokens, @@ -103,10 +103,10 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { vm.assume(protocolTaxPercentage <= MAX_PPM); vm.assume(queryFeeCut <= MAX_PPM); resetPrank(users.indexer); - _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); _storeAllocation(allocationTokens); _storeProtocolTaxAndCuration(curationPercentage, protocolTaxPercentage); _storeDelegationPool(delegationTokens, 0, queryFeeCut); + _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); curation.signal(_subgraphDeploymentID, curationTokens); resetPrank(users.gateway); @@ -138,7 +138,7 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { payment -= delegationFeeCut; } - assertEq(staking.getStake(address(users.indexer)), provisionTokens + payment); + assertEq(staking.getStake(address(users.indexer)), allocationTokens + provisionTokens + payment); assertEq(curation.curation(_subgraphDeploymentID), curationTokens + curationCutTokens); assertEq(staking.getDelegationPool(users.indexer, subgraphDataServiceLegacyAddress).tokens, delegationTokens + delegationFeeCut); assertEq(token.balanceOf(address(payments)), 0); From b56567e49eed99f31e88e99eca31fd3262969778 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 20 Aug 2024 18:48:06 -0300 Subject: [PATCH 179/277] fix: make fisherman deposit a fixed value (OZ L-01) --- .../contracts/DisputeManager.sol | 75 ++++++++++--------- .../contracts/DisputeManagerStorage.sol | 4 +- .../contracts/interfaces/IDisputeManager.sol | 17 ++--- .../test/SubgraphBaseTest.t.sol | 2 +- .../test/disputes/DisputeManager.t.sol | 18 +++-- .../test/disputes/accept.t.sol | 22 ++---- .../test/disputes/cancel.t.sol | 12 +-- .../test/disputes/create.t.sol | 49 +++++------- .../subgraph-service/test/disputes/draw.t.sol | 12 +-- .../subgraph-service/test/utils/Constants.sol | 2 +- 10 files changed, 94 insertions(+), 119 deletions(-) diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 6d4577153..5ad0d8d56 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -97,14 +97,14 @@ contract DisputeManager is * @notice Initialize this contract. * @param arbitrator Arbitrator role * @param disputePeriod Dispute period in seconds - * @param minimumDeposit Minimum deposit required to create a Dispute + * @param disputeDeposit Deposit required to create a Dispute * @param fishermanRewardCut_ Percent of slashed funds for fisherman (ppm) * @param maxSlashingCut_ Maximum percentage of indexer stake that can be slashed (ppm) */ function initialize( address arbitrator, uint64 disputePeriod, - uint256 minimumDeposit, + uint256 disputeDeposit, uint32 fishermanRewardCut_, uint32 maxSlashingCut_ ) external override initializer { @@ -113,7 +113,7 @@ contract DisputeManager is _setArbitrator(arbitrator); _setDisputePeriod(disputePeriod); - _setMinimumDeposit(minimumDeposit); + _setDisputeDeposit(disputeDeposit); _setFishermanRewardCut(fishermanRewardCut_); _setMaxSlashingCut(maxSlashingCut_); } @@ -122,40 +122,45 @@ contract DisputeManager is * @notice Create an indexing dispute for the arbitrator to resolve. * The disputes are created in reference to an allocationId and specifically * a POI for that allocation. - * This function is called by a challenger that will need to `_deposit` at - * least `minimumDeposit` GRT tokens. + * This function is called by a challenger and it will pull `disputeDeposit` GRT tokens. + * + * Requirements: + * - Challenger must have previously approved this contract to pull `disputeDeposit` amount + * of tokens from their balance. + * * @param allocationId The allocation to dispute * @param poi The Proof of Indexing (POI) being disputed - * @param deposit Amount of tokens staked as deposit */ function createIndexingDispute( address allocationId, - bytes32 poi, - uint256 deposit + bytes32 poi ) external override returns (bytes32) { // Get funds from submitter - _pullSubmitterDeposit(deposit); + _pullSubmitterDeposit(); // Create a dispute - return _createIndexingDisputeWithAllocation(msg.sender, deposit, allocationId, poi); + return _createIndexingDisputeWithAllocation(msg.sender, disputeDeposit, allocationId, poi); } /** * @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 - */ - function createQueryDispute(bytes calldata attestationData, uint256 deposit) external override returns (bytes32) { + * This function is called by a challenger and it will pull `disputeDeposit` GRT tokens. + * + * * Requirements: + * - Challenger must have previously approved this contract to pull `disputeDeposit` amount + * of tokens from their balance. + * + * @param attestationData Attestation bytes submitted by the challenger + */ + function createQueryDispute(bytes calldata attestationData) external override returns (bytes32) { // Get funds from submitter - _pullSubmitterDeposit(deposit); + _pullSubmitterDeposit(); // Create a dispute return _createQueryDisputeWithAttestation( msg.sender, - deposit, + disputeDeposit, Attestation.parse(attestationData), attestationData ); @@ -303,12 +308,12 @@ contract DisputeManager is } /** - * @notice Set the minimum deposit required to create a dispute. - * @dev Update the minimum deposit to `_minimumDeposit` Graph Tokens - * @param minimumDeposit The minimum deposit in Graph Tokens + * @notice Set the dispute deposit required to create a dispute. + * @dev Update the dispute deposit to `_disputeDeposit` Graph Tokens + * @param disputeDeposit The dispute deposit in Graph Tokens */ - function setMinimumDeposit(uint256 minimumDeposit) external override onlyOwner { - _setMinimumDeposit(minimumDeposit); + function setDisputeDeposit(uint256 disputeDeposit) external override onlyOwner { + _setDisputeDeposit(disputeDeposit); } /** @@ -577,15 +582,11 @@ contract DisputeManager is } /** - * @notice Pull deposit from submitter account. - * @param _deposit Amount of tokens to deposit + * @notice Pull `disputeDeposit` from submitter account. */ - function _pullSubmitterDeposit(uint256 _deposit) private { - // Ensure that fisherman has staked at least the minimum amount - require(_deposit >= minimumDeposit, DisputeManagerInsufficientDeposit(_deposit, minimumDeposit)); - + function _pullSubmitterDeposit() private { // Transfer tokens to deposit from fisherman to this contract - _graphToken().pullTokens(msg.sender, _deposit); + _graphToken().pullTokens(msg.sender, disputeDeposit); } /** @@ -642,14 +643,14 @@ contract DisputeManager is } /** - * @notice Internal: Set the minimum deposit required to create a dispute. - * @dev Update the minimum deposit to `_minimumDeposit` Graph Tokens - * @param _minimumDeposit The minimum deposit in Graph Tokens + * @notice Internal: Set the dispute deposit required to create a dispute. + * @dev Update the dispute deposit to `_disputeDeposit` Graph Tokens + * @param _disputeDeposit The dispute deposit in Graph Tokens */ - function _setMinimumDeposit(uint256 _minimumDeposit) private { - require(_minimumDeposit != 0, DisputeManagerInvalidMinimumDeposit(_minimumDeposit)); - minimumDeposit = _minimumDeposit; - emit MinimumDepositSet(minimumDeposit); + function _setDisputeDeposit(uint256 _disputeDeposit) private { + require(_disputeDeposit != 0, DisputeManagerInvalidDisputeDeposit(_disputeDeposit)); + disputeDeposit = _disputeDeposit; + emit DisputeDepositSet(disputeDeposit); } /** diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol index 19e217f12..8ff0685bf 100644 --- a/packages/subgraph-service/contracts/DisputeManagerStorage.sol +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -15,8 +15,8 @@ abstract contract DisputeManagerV1Storage { /// @notice dispute period in seconds uint64 public disputePeriod; - /// @notice Minimum deposit required to create a Dispute - uint256 public minimumDeposit; + /// @notice Deposit required to create a Dispute + uint256 public disputeDeposit; /// @notice Percentage of indexer slashed funds to assign as a reward to fisherman in successful dispute. In PPM. uint32 public fishermanRewardCut; diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index b0616824d..09b13aec4 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -55,10 +55,10 @@ interface IDisputeManager { event DisputePeriodSet(uint64 disputePeriod); /** - * @notice Emitted when minimum deposit is set. - * @param minimumDeposit The minimum deposit required to create a dispute. + * @notice Emitted when dispute deposit is set. + * @param disputeDeposit The dispute deposit required to create a dispute. */ - event MinimumDepositSet(uint256 minimumDeposit); + event DisputeDepositSet(uint256 disputeDeposit); /** * @notice Emitted when max slashing cut is set. @@ -151,12 +151,11 @@ interface IDisputeManager { error DisputeManagerDisputePeriodZero(); error DisputeManagerZeroTokens(); error DisputeManagerInvalidDispute(bytes32 disputeId); - error DisputeManagerInvalidMinimumDeposit(uint256 minimumDeposit); + error DisputeManagerInvalidDisputeDeposit(uint256 disputeDeposit); error DisputeManagerInvalidFishermanReward(uint32 cut); error DisputeManagerInvalidMaxSlashingCut(uint32 maxSlashingCut); error DisputeManagerInvalidTokensSlash(uint256 tokensSlash, uint256 maxTokensSlash); error DisputeManagerDisputeNotPending(IDisputeManager.DisputeStatus status); - error DisputeManagerInsufficientDeposit(uint256 deposit, uint256 minimumDeposit); error DisputeManagerDisputeAlreadyCreated(bytes32 disputeId); error DisputeManagerDisputePeriodNotFinished(); error DisputeManagerMustAcceptRelatedDispute(bytes32 disputeId, bytes32 relatedDisputeId); @@ -174,7 +173,7 @@ interface IDisputeManager { function initialize( address arbitrator, uint64 disputePeriod, - uint256 minimumDeposit, + uint256 disputeDeposit, uint32 fishermanRewardCut, uint32 maxSlashingCut ) external; @@ -183,7 +182,7 @@ interface IDisputeManager { function setArbitrator(address arbitrator) external; - function setMinimumDeposit(uint256 minimumDeposit) external; + function setDisputeDeposit(uint256 disputeDeposit) external; function setFishermanRewardCut(uint32 cut) external; @@ -191,14 +190,14 @@ interface IDisputeManager { // -- Dispute -- - function createQueryDispute(bytes calldata attestationData, uint256 deposit) external returns (bytes32); + function createQueryDispute(bytes calldata attestationData) external returns (bytes32); function createQueryDisputeConflict( bytes calldata attestationData1, bytes calldata attestationData2 ) external returns (bytes32, bytes32); - function createIndexingDispute(address allocationId, bytes32 poi, uint256 deposit) external returns (bytes32); + function createIndexingDispute(address allocationId, bytes32 poi) external returns (bytes32); function acceptDispute(bytes32 disputeId, uint256 tokensSlash) external; diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 1ebcf6683..a381d1695 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -138,7 +138,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { users.governor, abi.encodeCall( DisputeManager.initialize, - (users.arbitrator, disputePeriod, minimumDeposit, fishermanRewardPercentage, maxSlashingPercentage) + (users.arbitrator, disputePeriod, disputeDeposit, fishermanRewardPercentage, maxSlashingPercentage) ) ); disputeManager = DisputeManager(disputeManagerProxy); diff --git a/packages/subgraph-service/test/disputes/DisputeManager.t.sol b/packages/subgraph-service/test/disputes/DisputeManager.t.sol index 8b6f95b12..954cef783 100644 --- a/packages/subgraph-service/test/disputes/DisputeManager.t.sol +++ b/packages/subgraph-service/test/disputes/DisputeManager.t.sol @@ -28,17 +28,20 @@ contract DisputeManagerTest is SubgraphServiceSharedTest { * HELPERS */ - function _createIndexingDispute(address _allocationID, bytes32 _poi, uint256 tokens) internal returns (bytes32 disputeID) { + function _createIndexingDispute(address _allocationID, bytes32 _poi) internal returns (bytes32 disputeID) { address msgSender; (, msgSender,) = vm.readCallers(); resetPrank(users.fisherman); - token.approve(address(disputeManager), tokens); - bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, _poi, tokens); + uint256 beforeFishermanBalance = token.balanceOf(users.fisherman); + token.approve(address(disputeManager), disputeDeposit); + bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, _poi); + uint256 afterFishermanBalance = token.balanceOf(users.fisherman); + assertEq(afterFishermanBalance, beforeFishermanBalance - disputeDeposit, "Fisherman should be charged the dispute deposit"); resetPrank(msgSender); return _disputeID; } - function _createQueryDispute(uint256 tokens) internal returns (bytes32 disputeID) { + function _createQueryDispute() internal returns (bytes32 disputeID) { address msgSender; (, msgSender,) = vm.readCallers(); resetPrank(users.fisherman); @@ -49,8 +52,11 @@ contract DisputeManagerTest is SubgraphServiceSharedTest { }); bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); - token.approve(address(disputeManager), tokens); - bytes32 _disputeID = disputeManager.createQueryDispute(attestationData, tokens); + uint256 beforeFishermanBalance = token.balanceOf(users.fisherman); + token.approve(address(disputeManager), disputeDeposit); + bytes32 _disputeID = disputeManager.createQueryDispute(attestationData); + uint256 afterFishermanBalance = token.balanceOf(users.fisherman); + assertEq(afterFishermanBalance, beforeFishermanBalance - disputeDeposit, "Fisherman should be charged the dispute deposit"); resetPrank(msgSender); return _disputeID; } diff --git a/packages/subgraph-service/test/disputes/accept.t.sol b/packages/subgraph-service/test/disputes/accept.t.sol index ee9bbec27..8e7a7f593 100644 --- a/packages/subgraph-service/test/disputes/accept.t.sol +++ b/packages/subgraph-service/test/disputes/accept.t.sol @@ -17,7 +17,6 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_IndexingDispute( uint256 tokens, - uint256 tokensDispute, uint256 tokensSlash, uint256 delegationAmount ) public useIndexer useAllocation(tokens) { @@ -29,10 +28,9 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); tokensSlash = bound(tokensSlash, 1, tokensSlashCap); - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); resetPrank(users.arbitrator); disputeManager.acceptDispute(disputeID, tokensSlash); @@ -44,7 +42,6 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_QueryDispute( uint256 tokens, - uint256 tokensDispute, uint256 tokensSlash, uint256 delegationAmount ) public useIndexer useAllocation(tokens) { @@ -56,10 +53,9 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); tokensSlash = bound(tokensSlash, 1, tokensSlashCap); - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID = _createQueryDispute(tokensDispute); + bytes32 disputeID = _createQueryDispute(); resetPrank(users.arbitrator); disputeManager.acceptDispute(disputeID, tokensSlash); @@ -120,7 +116,6 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_IndexingDispute_RevertIf_SlashAmountTooHigh( uint256 tokens, - uint256 tokensDispute, uint256 tokensSlash, uint256 delegationAmount ) public useIndexer useAllocation(tokens) { @@ -132,9 +127,8 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); resetPrank(users.arbitrator); bytes memory expectedError = abi.encodeWithSelector( @@ -148,7 +142,6 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_QueryDispute_RevertIf_SlashAmountTooHigh( uint256 tokens, - uint256 tokensDispute, uint256 tokensSlash, uint256 delegationAmount ) public useIndexer useAllocation(tokens) { @@ -160,9 +153,8 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID = _createQueryDispute(tokensDispute); + bytes32 disputeID = _createQueryDispute(); resetPrank(users.arbitrator); bytes memory expectedError = abi.encodeWithSelector( @@ -176,7 +168,6 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_ConflictingQueryDispute_RevertIf_SlashAmountTooHigh( uint256 tokens, - uint256 tokensDispute, uint256 tokensSlash, uint256 delegationAmount ) public useIndexer useAllocation(tokens) { @@ -188,7 +179,6 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); @@ -219,13 +209,11 @@ contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { function testAccept_RevertIf_CallerIsNotArbitrator( uint256 tokens, - uint256 tokensDispute, uint256 tokensSlash ) public useIndexer useAllocation(tokens) { tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); // attempt to accept dispute as fisherman resetPrank(users.fisherman); diff --git a/packages/subgraph-service/test/disputes/cancel.t.sol b/packages/subgraph-service/test/disputes/cancel.t.sol index f61e7c099..4affbd6f4 100644 --- a/packages/subgraph-service/test/disputes/cancel.t.sol +++ b/packages/subgraph-service/test/disputes/cancel.t.sol @@ -13,12 +13,10 @@ contract DisputeManagerCancelDisputeTest is DisputeManagerTest { */ function testCancel_Dispute( - uint256 tokens, - uint256 tokensDispute + uint256 tokens ) public useIndexer useAllocation(tokens) { - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); // skip to end of dispute period skip(disputePeriod + 1); @@ -61,11 +59,9 @@ contract DisputeManagerCancelDisputeTest is DisputeManagerTest { } function testCancel_RevertIf_CallerIsNotFisherman( - uint256 tokens, - uint256 tokensDispute + uint256 tokens ) public useIndexer useAllocation(tokens) { - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); resetPrank(users.arbitrator); vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotFisherman.selector)); diff --git a/packages/subgraph-service/test/disputes/create.t.sol b/packages/subgraph-service/test/disputes/create.t.sol index 5112aea0a..eb1907ebe 100644 --- a/packages/subgraph-service/test/disputes/create.t.sol +++ b/packages/subgraph-service/test/disputes/create.t.sol @@ -13,20 +13,16 @@ contract DisputeManagerCreateDisputeTest is DisputeManagerTest { */ function testCreate_IndexingDispute( - uint256 tokens, - uint256 tokensDispute + uint256 tokens ) public useIndexer useAllocation(tokens) { - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); } function testCreate_QueryDispute( - uint256 tokens, - uint256 tokensDispute + uint256 tokens ) public useIndexer useAllocation(tokens) { - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID = _createQueryDispute(tokensDispute); + bytes32 disputeID = _createQueryDispute(); assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); } @@ -54,51 +50,44 @@ contract DisputeManagerCreateDisputeTest is DisputeManagerTest { } function testCreate_RevertWhen_DisputeAlreadyCreated( - uint256 tokens, - uint256 tokensDispute + uint256 tokens ) public useIndexer useAllocation(tokens) { - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); // Create another dispute with different fisherman address otherFisherman = makeAddr("otherFisherman"); resetPrank(otherFisherman); - mint(otherFisherman, tokensDispute); - token.approve(address(disputeManager), tokensDispute); + mint(otherFisherman, disputeDeposit); + token.approve(address(disputeManager), disputeDeposit); bytes memory expectedError = abi.encodeWithSelector( IDisputeManager.DisputeManagerDisputeAlreadyCreated.selector, disputeID ); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI1"), tokensDispute); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1")); vm.stopPrank(); } - function testCreate_RevertIf_DepositUnderMinimum( - uint256 tokensDispute - ) public useFisherman { - tokensDispute = bound(tokensDispute, 1, minimumDeposit - 1); - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerInsufficientDeposit.selector, - tokensDispute, - minimumDeposit + function testCreate_RevertIf_TokensNotApproved() public useFisherman { + bytes memory expectedError = abi.encodeWithSignature( + "ERC20InsufficientAllowance(address,uint256,uint256)", + address(disputeManager), + 0, + disputeDeposit ); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI3"), tokensDispute); + disputeManager.createIndexingDispute(allocationID, bytes32("POI3")); vm.stopPrank(); } - function testCreate_RevertIf_AllocationDoesNotExist( - uint256 tokens - ) public useFisherman { - tokens = bound(tokens, minimumDeposit, 10_000_000_000 ether); - token.approve(address(disputeManager), tokens); + function testCreate_RevertIf_AllocationDoesNotExist() public useFisherman { + token.approve(address(disputeManager), disputeDeposit); bytes memory expectedError = abi.encodeWithSelector( IDisputeManager.DisputeManagerIndexerNotFound.selector, allocationID ); vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI4"), tokens); + disputeManager.createIndexingDispute(allocationID, bytes32("POI4")); vm.stopPrank(); } diff --git a/packages/subgraph-service/test/disputes/draw.t.sol b/packages/subgraph-service/test/disputes/draw.t.sol index e28561b10..e5ef827de 100644 --- a/packages/subgraph-service/test/disputes/draw.t.sol +++ b/packages/subgraph-service/test/disputes/draw.t.sol @@ -14,12 +14,10 @@ contract DisputeManagerDrawDisputeTest is DisputeManagerTest { */ function testDraw_Dispute( - uint256 tokens, - uint256 tokensDispute + uint256 tokens ) public useIndexer useAllocation(tokens) { - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI32"), tokensDispute); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI32")); resetPrank(users.arbitrator); disputeManager.drawDispute(disputeID); @@ -57,11 +55,9 @@ contract DisputeManagerDrawDisputeTest is DisputeManagerTest { } function testDraw_RevertIf_CallerIsNotArbitrator( - uint256 tokens, - uint256 tokensDispute + uint256 tokens ) public useIndexer useAllocation(tokens) { - tokensDispute = bound(tokensDispute, minimumDeposit, tokens); - bytes32 disputeID =_createIndexingDispute(allocationID,bytes32("POI1"), tokens); + bytes32 disputeID = _createIndexingDispute(allocationID,bytes32("POI1")); // attempt to draw dispute as fisherman resetPrank(users.fisherman); diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index e533fd549..b28362653 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -5,7 +5,7 @@ abstract contract Constants { uint256 internal constant MAX_TOKENS = 10_000_000_000 ether; // Dispute Manager uint64 internal constant disputePeriod = 300; // 5 minutes - uint256 internal constant minimumDeposit = 100 ether; // 100 GRT + uint256 internal constant disputeDeposit = 100 ether; // 100 GRT uint32 internal constant fishermanRewardPercentage = 100000; // 10% uint32 internal constant maxSlashingPercentage = 500000; // 50% // Subgraph Service From dc3add0b1253c6e47d2a4c60c435d92d2af6d4e8 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 21 Aug 2024 12:39:55 -0300 Subject: [PATCH 180/277] fix: add max fisherman rewards cut (OZ L-02) --- .../contracts/DisputeManager.sol | 8 +- .../test/SubgraphBaseTest.t.sol | 4 +- .../DisputeManager.t.sol | 6 + .../constructor/constructor.t.sol | 166 ++++++++++++++++++ .../disputes/accept.t.sol | 4 +- .../disputes/cancel.t.sol | 4 +- .../disputes/create.t.sol | 4 +- .../{ => disputeManager}/disputes/draw.t.sol | 4 +- .../governance/fishermanRewardCut.t.sol | 33 ++++ 9 files changed, 221 insertions(+), 12 deletions(-) rename packages/subgraph-service/test/{disputes => disputeManager}/DisputeManager.t.sol (97%) create mode 100644 packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol rename packages/subgraph-service/test/{ => disputeManager}/disputes/accept.t.sol (98%) rename packages/subgraph-service/test/{ => disputeManager}/disputes/cancel.t.sol (94%) rename packages/subgraph-service/test/{ => disputeManager}/disputes/create.t.sol (97%) rename packages/subgraph-service/test/{ => disputeManager}/disputes/draw.t.sol (94%) create mode 100644 packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 5ad0d8d56..f234057aa 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -52,6 +52,11 @@ contract DisputeManager is using TokenUtils for IGraphToken; using PPMMath for uint256; + // -- Constants -- + + // Maximum value for fisherman reward cut in PPM + uint32 public constant MAX_FISHERMAN_REWARD_CUT = 500000; + // -- Modifiers -- /** @@ -659,8 +664,7 @@ contract DisputeManager is * @param _fishermanRewardCut Reward as a percentage of indexer stake */ function _setFishermanRewardCut(uint32 _fishermanRewardCut) private { - // Must be within 0% to 100% (inclusive) - require(PPMMath.isValidPPM(_fishermanRewardCut), DisputeManagerInvalidFishermanReward(_fishermanRewardCut)); + require(_fishermanRewardCut <= MAX_FISHERMAN_REWARD_CUT, DisputeManagerInvalidFishermanReward(_fishermanRewardCut)); fishermanRewardCut = _fishermanRewardCut; emit FishermanRewardCutSet(fishermanRewardCut); } diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index a381d1695..9991ab8a5 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -142,6 +142,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { ) ); disputeManager = DisputeManager(disputeManagerProxy); + disputeManager.transferOwnership(users.governor); tapCollector = new TAPCollector("TAPCollector", "1", address(controller)); address subgraphServiceImplementation = address( @@ -154,8 +155,6 @@ abstract contract SubgraphBaseTest is Utils, Constants { ); subgraphService = SubgraphService(subgraphServiceProxy); - disputeManager.setSubgraphService(address(subgraphService)); - stakingExtension = new HorizonStakingExtension( address(controller), address(subgraphService) @@ -177,6 +176,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { ); resetPrank(users.governor); + disputeManager.setSubgraphService(address(subgraphService)); proxyAdmin.upgrade(stakingProxy, address(stakingBase)); proxyAdmin.acceptProxy(stakingBase, stakingProxy); staking = IHorizonStaking(address(stakingProxy)); diff --git a/packages/subgraph-service/test/disputes/DisputeManager.t.sol b/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol similarity index 97% rename from packages/subgraph-service/test/disputes/DisputeManager.t.sol rename to packages/subgraph-service/test/disputeManager/DisputeManager.t.sol index 954cef783..9f80512b4 100644 --- a/packages/subgraph-service/test/disputes/DisputeManager.t.sol +++ b/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol @@ -18,6 +18,12 @@ contract DisputeManagerTest is SubgraphServiceSharedTest { * MODIFIERS */ + modifier useGovernor() { + vm.startPrank(users.governor); + _; + vm.stopPrank(); + } + modifier useFisherman { vm.startPrank(users.fisherman); _; diff --git a/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol b/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol new file mode 100644 index 000000000..d4f100f68 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/GraphDirectory.sol"; +import { UnsafeUpgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; +import { DisputeManager } from "../../../contracts/DisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; + +contract DisputeManagerConstructorTest is DisputeManagerTest { + using PPMMath for uint256; + + /* + * MODIFIERS + */ + + modifier useDeployer() { + vm.startPrank(users.deployer); + _; + vm.stopPrank(); + } + + /* + * HELPERS + */ + + function _initializeDisputeManager( + address implementation, + address arbitrator, + uint64 disputePeriod, + uint256 disputeDeposit, + uint32 fishermanRewardPercentage, + uint32 maxSlashingPercentage + ) private returns (address) { + return UnsafeUpgrades.deployTransparentProxy( + implementation, + users.governor, + abi.encodeCall( + DisputeManager.initialize, + (arbitrator, disputePeriod, disputeDeposit, fishermanRewardPercentage, maxSlashingPercentage) + ) + ); + } + + /* + * TESTS + */ + + function test_Constructor( + uint32 fishermanRewardPercentage + ) public useDeployer { + vm.assume(fishermanRewardPercentage <= disputeManager.MAX_FISHERMAN_REWARD_CUT()); + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + address proxy = _initializeDisputeManager( + disputeManagerImplementation, + users.arbitrator, + disputePeriod, + disputeDeposit, + fishermanRewardPercentage, + maxSlashingPercentage + ); + + DisputeManager disputeManager = DisputeManager(proxy); + assertEq(disputeManager.arbitrator(), users.arbitrator); + assertEq(disputeManager.disputePeriod(), disputePeriod); + assertEq(disputeManager.disputeDeposit(), disputeDeposit); + assertEq(disputeManager.fishermanRewardCut(), fishermanRewardPercentage); + } + + function test_Constructor_RevertIf_ControllerAddressIsZero() public useDeployer { + bytes memory expectedError = abi.encodeWithSelector( + GraphDirectory.GraphDirectoryInvalidZeroAddress.selector, + "Controller" + ); + vm.expectRevert(expectedError); + new DisputeManager(address(0)); + } + + function test_Constructor_RevertIf_ArbitratorAddressIsZero() public useDeployer { + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidZeroAddress.selector + ); + vm.expectRevert(expectedError); + _initializeDisputeManager( + disputeManagerImplementation, + address(0), + disputePeriod, + disputeDeposit, + fishermanRewardPercentage, + maxSlashingPercentage + ); + } + + function test_Constructor_RevertIf_InvalidDisputePeriod() public useDeployer { + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerDisputePeriodZero.selector + ); + vm.expectRevert(expectedError); + _initializeDisputeManager( + disputeManagerImplementation, + users.arbitrator, + 0, + disputeDeposit, + fishermanRewardPercentage, + maxSlashingPercentage + ); + } + + function test_Constructor_RevertIf_InvalidDisputeDeposit() public useDeployer { + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidDisputeDeposit.selector, + 0 + ); + vm.expectRevert(expectedError); + _initializeDisputeManager( + disputeManagerImplementation, + users.arbitrator, + disputePeriod, + 0, + fishermanRewardPercentage, + maxSlashingPercentage + ); + } + + function test_Constructor_RevertIf_InvalidFishermanRewardPercentage(uint32 _fishermanRewardPercentage) public useDeployer { + vm.assume(_fishermanRewardPercentage > disputeManager.MAX_FISHERMAN_REWARD_CUT()); + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidFishermanReward.selector, + _fishermanRewardPercentage + ); + vm.expectRevert(expectedError); + _initializeDisputeManager( + disputeManagerImplementation, + users.arbitrator, + disputePeriod, + disputeDeposit, + _fishermanRewardPercentage, + maxSlashingPercentage + ); + } + + function test_Constructor_RevertIf_InvalidMaxSlashingPercentage(uint32 _maxSlashingPercentage) public useDeployer { + vm.assume(_maxSlashingPercentage > PPMMath.MAX_PPM); + address disputeManagerImplementation = address(new DisputeManager(address(controller))); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidMaxSlashingCut.selector, + _maxSlashingPercentage + ); + vm.expectRevert(expectedError); + _initializeDisputeManager( + disputeManagerImplementation, + users.arbitrator, + disputePeriod, + disputeDeposit, + fishermanRewardPercentage, + _maxSlashingPercentage + ); + } +} \ No newline at end of file diff --git a/packages/subgraph-service/test/disputes/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/accept.t.sol similarity index 98% rename from packages/subgraph-service/test/disputes/accept.t.sol rename to packages/subgraph-service/test/disputeManager/disputes/accept.t.sol index 8e7a7f593..29e3bb6f5 100644 --- a/packages/subgraph-service/test/disputes/accept.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/accept.t.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; -import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "./DisputeManager.t.sol"; +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { diff --git a/packages/subgraph-service/test/disputes/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/cancel.t.sol similarity index 94% rename from packages/subgraph-service/test/disputes/cancel.t.sol rename to packages/subgraph-service/test/disputeManager/disputes/cancel.t.sol index 4affbd6f4..abd55e051 100644 --- a/packages/subgraph-service/test/disputes/cancel.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/cancel.t.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "./DisputeManager.t.sol"; +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; contract DisputeManagerCancelDisputeTest is DisputeManagerTest { diff --git a/packages/subgraph-service/test/disputes/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/create.t.sol similarity index 97% rename from packages/subgraph-service/test/disputes/create.t.sol rename to packages/subgraph-service/test/disputeManager/disputes/create.t.sol index eb1907ebe..05147ec73 100644 --- a/packages/subgraph-service/test/disputes/create.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/create.t.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "./DisputeManager.t.sol"; +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; contract DisputeManagerCreateDisputeTest is DisputeManagerTest { diff --git a/packages/subgraph-service/test/disputes/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/draw.t.sol similarity index 94% rename from packages/subgraph-service/test/disputes/draw.t.sol rename to packages/subgraph-service/test/disputeManager/disputes/draw.t.sol index e5ef827de..75dabaa2f 100644 --- a/packages/subgraph-service/test/disputes/draw.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/draw.t.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; -import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "./DisputeManager.t.sol"; +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; contract DisputeManagerDrawDisputeTest is DisputeManagerTest { diff --git a/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol b/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol new file mode 100644 index 000000000..0c821e2a2 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +contract DisputeManagerGovernanceFishermanRewardCutTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Governance_SetFishermanRewardCut() public useGovernor { + uint32 fishermanRewardCut = 1000; + disputeManager.setFishermanRewardCut(fishermanRewardCut); + assertEq(disputeManager.fishermanRewardCut(), fishermanRewardCut, "Fisherman reward cut should be set."); + } + + function test_Governance_RevertWhen_OverMaximumValue(uint32 fishermanRewardCut) public useGovernor { + vm.assume(fishermanRewardCut > disputeManager.MAX_FISHERMAN_REWARD_CUT()); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerInvalidFishermanReward.selector, fishermanRewardCut)); + disputeManager.setFishermanRewardCut(fishermanRewardCut); + } + + function test_Governance_RevertWhen_NotGovernor() public useFisherman { + uint32 fishermanRewardCut = 1000; + vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, users.fisherman)); + disputeManager.setFishermanRewardCut(fishermanRewardCut); + } +} \ No newline at end of file From 3aeb4b6456d517b704edd4588248e21d261bbdba Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 22 Aug 2024 12:03:00 -0300 Subject: [PATCH 181/277] fix: make PaymentsEscrow upgradable and pausable (OZ L-03) --- .../contracts/interfaces/IPaymentsEscrow.sol | 10 +++ .../contracts/payments/PaymentsEscrow.sol | 41 ++++++--- packages/horizon/test/GraphBase.t.sol | 42 +++++---- .../horizon/test/escrow/GraphEscrow.t.sol | 8 ++ packages/horizon/test/escrow/paused.t.sol | 88 +++++++++++++++++++ packages/horizon/test/escrow/withdraw.t.sol | 12 --- 6 files changed, 159 insertions(+), 42 deletions(-) create mode 100644 packages/horizon/test/escrow/paused.t.sol diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 6d9396d00..b7ed62864 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -113,6 +113,11 @@ interface IPaymentsEscrow { // -- Errors -- + /** + * @notice Thrown when a protected function is called and the contract is paused. + */ + error PaymentsEscrowIsPaused(); + /** * @notice Thrown when the available balance is insufficient to perform an operation * @param balance The current balance @@ -168,6 +173,11 @@ interface IPaymentsEscrow { */ error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); + /** + * @notice Initialize the contract + */ + function initialize() external; + /** * @notice Authorize a collector to collect funds from the payer's escrow * @dev This function can only be used to increase the allowance of a collector. diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 6f5ee9282..37cc1047f 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -5,7 +5,8 @@ import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToke import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; import { IPaymentsEscrow } from "../interfaces/IPaymentsEscrow.sol"; -import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { MulticallUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { GraphDirectory } from "../utilities/GraphDirectory.sol"; @@ -17,7 +18,12 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; * for payments made through the payments protocol for services provided * via a Graph Horizon data service. */ -contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { +contract PaymentsEscrow is + Initializable, + MulticallUpgradeable, + GraphDirectory, + IPaymentsEscrow +{ using TokenUtils for IGraphToken; /// @notice Authorization details for payer-collector pairs @@ -38,6 +44,11 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { /// @notice Thawing period in seconds for escrow funds withdrawal uint256 public immutable WITHDRAW_ESCROW_THAWING_PERIOD; + modifier notPaused() { + require(!_graphController().paused(), PaymentsEscrowIsPaused()); + _; + } + /** * @notice Construct the PaymentsEscrow contract * @param controller The address of the controller @@ -62,10 +73,18 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { WITHDRAW_ESCROW_THAWING_PERIOD = withdrawEscrowThawingPeriod; } + + /** + * @notice See {PaymentsEscrow.initialize} + */ + function initialize() external override initializer { + __Multicall_init(); + } + /** * @notice See {IPaymentsEscrow-approveCollector} */ - function approveCollector(address collector_, uint256 allowance) external override { + function approveCollector(address collector_, uint256 allowance) external override notPaused { Collector storage collector = authorizedCollectors[msg.sender][collector_]; require(allowance > collector.allowance, PaymentsEscrowInconsistentAllowance(collector.allowance, allowance)); @@ -77,7 +96,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { /** * @notice See {IPaymentsEscrow-thawCollector} */ - function thawCollector(address collector) external override { + function thawCollector(address collector) external override notPaused { authorizedCollectors[msg.sender][collector].thawEndTimestamp = block.timestamp + REVOKE_COLLECTOR_THAWING_PERIOD; @@ -87,7 +106,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { /** * @notice See {IPaymentsEscrow-cancelThawCollector} */ - function cancelThawCollector(address collector) external override { + function cancelThawCollector(address collector) external override notPaused { require(authorizedCollectors[msg.sender][collector].thawEndTimestamp != 0, PaymentsEscrowNotThawing()); authorizedCollectors[msg.sender][collector].thawEndTimestamp = 0; @@ -97,7 +116,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { /** * @notice See {IPaymentsEscrow-revokeCollector} */ - function revokeCollector(address collector_) external override { + function revokeCollector(address collector_) external override notPaused { Collector storage collector = authorizedCollectors[msg.sender][collector_]; require(collector.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); @@ -113,21 +132,21 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { /** * @notice See {IPaymentsEscrow-deposit} */ - function deposit(address receiver, uint256 tokens) external override { + function deposit(address receiver, uint256 tokens) external override notPaused { _deposit(msg.sender, receiver, tokens); } /** * @notice See {IPaymentsEscrow-depositTo} */ - function depositTo(address payer, address receiver, uint256 tokens) external override { + function depositTo(address payer, address receiver, uint256 tokens) external override notPaused { _deposit(payer, receiver, tokens); } /** * @notice See {IPaymentsEscrow-thaw} */ - function thaw(address receiver, uint256 tokens) external override { + function thaw(address receiver, uint256 tokens) external override notPaused { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; // if amount thawing is zero and requested amount is zero this is an invalid request. @@ -152,7 +171,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { /** * @notice See {IPaymentsEscrow-withdraw} */ - function withdraw(address receiver) external override { + function withdraw(address receiver) external override notPaused { EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; require(account.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); require( @@ -180,7 +199,7 @@ contract PaymentsEscrow is Multicall, GraphDirectory, IPaymentsEscrow { uint256 tokens, address dataService, uint256 tokensDataService - ) external override { + ) external override notPaused { // Check if collector is authorized and has enough funds Collector storage collector = authorizedCollectors[payer][msg.sender]; require(collector.authorized, PaymentsEscrowCollectorNotAuthorized(payer, msg.sender)); diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 7126c5313..f93009d20 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -6,6 +6,7 @@ import "forge-std/Test.sol"; import { GraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/GraphProxyAdmin.sol"; import { GraphProxy } from "@graphprotocol/contracts/contracts/upgrades/GraphProxy.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { PaymentsEscrow } from "contracts/payments/PaymentsEscrow.sol"; import { GraphPayments } from "contracts/payments/GraphPayments.sol"; @@ -114,19 +115,15 @@ abstract contract GraphBaseTest is Utils, Constants { users.deployer ); - // GraphEscrow predict address - bytes32 saltEscrow = keccak256("GraphEscrowSalt"); - bytes32 escrowHash = keccak256(bytes.concat( - vm.getCode("PaymentsEscrow.sol:PaymentsEscrow"), - abi.encode( - address(controller), - revokeCollectorThawingPeriod, - withdrawEscrowThawingPeriod - ) + // PaymentsEscrow + bytes32 escrowProxySalt = keccak256("PaymentsEscrowSalt"); + bytes32 escrowProxyHash = keccak256(bytes.concat( + vm.getCode("TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy"), + abi.encode(address(controller)) )); - address predictedAddressEscrow = vm.computeCreate2Address( - saltEscrow, - escrowHash, + address predictedEscrowProxyAddress = vm.computeCreate2Address( + escrowProxySalt, + escrowProxyHash, users.deployer ); @@ -142,7 +139,7 @@ abstract contract GraphBaseTest is Utils, Constants { // Setup controller resetPrank(users.governor); controller.setContractProxy(keccak256("GraphToken"), address(token)); - controller.setContractProxy(keccak256("PaymentsEscrow"), predictedAddressEscrow); + controller.setContractProxy(keccak256("PaymentsEscrow"), predictedEscrowProxyAddress); controller.setContractProxy(keccak256("GraphPayments"), predictedPaymentsAddress); controller.setContractProxy(keccak256("Staking"), address(stakingProxy)); controller.setContractProxy(keccak256("EpochManager"), address(epochManager)); @@ -153,14 +150,21 @@ abstract contract GraphBaseTest is Utils, Constants { resetPrank(users.deployer); payments = new GraphPayments{salt: saltPayments}( - address(controller), - protocolPaymentCut - ); - escrow = new PaymentsEscrow{salt: saltEscrow}( address(controller), - revokeCollectorThawingPeriod, - withdrawEscrowThawingPeriod + protocolPaymentCut ); + + address escrowImplementation = address(new PaymentsEscrow(address(controller), revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod)); + address escrowProxy = address(new TransparentUpgradeableProxy{salt: escrowProxySalt}( + escrowImplementation, + users.governor, + abi.encodeCall( + PaymentsEscrow.initialize, + () + ) + )); + escrow = PaymentsEscrow(escrowProxy); + stakingExtension = new HorizonStakingExtension( address(controller), subgraphDataServiceLegacyAddress diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index c94d221df..a510f57bf 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -35,6 +35,14 @@ contract GraphEscrowTest is HorizonStakingSharedTest { _; } + modifier depositAndThawTokens(uint256 amount, uint256 thawAmount) { + vm.assume(thawAmount > 0); + vm.assume(amount > thawAmount); + _depositTokens(amount); + escrow.thaw(users.indexer, thawAmount); + _; + } + /* * HELPERS */ diff --git a/packages/horizon/test/escrow/paused.t.sol b/packages/horizon/test/escrow/paused.t.sol new file mode 100644 index 000000000..2be37a61b --- /dev/null +++ b/packages/horizon/test/escrow/paused.t.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; +import { IPaymentsEscrow } from "../../contracts/interfaces/IPaymentsEscrow.sol"; + +import { GraphEscrowTest } from "./GraphEscrow.t.sol"; + +contract GraphEscrowPausedTest is GraphEscrowTest { + + /* + * MODIFIERS + */ + + modifier usePaused(bool paused) { + address msgSender; + (, msgSender,) = vm.readCallers(); + resetPrank(users.governor); + controller.setPaused(paused); + resetPrank(msgSender); + _; + } + + /* + * TESTS + */ + + // Escrow + + function testPaused_RevertWhen_Deposit(uint256 tokens) public useGateway usePaused(true) { + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.deposit(users.indexer, tokens); + } + + function testPaused_RevertWhen_DepositTo(uint256 tokens) public usePaused(true) { + resetPrank(users.operator); + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.depositTo(users.gateway, users.indexer, tokens); + } + + function testPaused_RevertWhen_ThawTokens(uint256 tokens) public useGateway useDeposit(tokens) usePaused(true) { + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.thaw(users.indexer, tokens); + } + + function testPaused_RevertWhen_WithdrawTokens( + uint256 tokens, + uint256 thawAmount + ) public useGateway depositAndThawTokens(tokens, thawAmount) usePaused(true) { + // advance time + skip(withdrawEscrowThawingPeriod + 1); + + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.withdraw(users.indexer); + } + + // Collect + + function testPaused_RevertWhen_CollectTokens(uint256 tokens, uint256 tokensDataService) public usePaused(true) { + resetPrank(users.verifier); + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, tokens, subgraphDataServiceAddress, tokensDataService); + } + + // Collectors + + function testPaused_RevertWhen_ApproveCollector(uint256 tokens) public useGateway usePaused(true) { + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.approveCollector(users.verifier, tokens); + } + + function testPaused_RevertWhen_ThawCollector(uint256 tokens) public useGateway useCollector(tokens) usePaused(true) { + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.thawCollector(users.verifier); + } + + function testPaused_RevertWhen_CancelThawCollector(uint256 tokens) public useGateway useCollector(tokens) usePaused(true) { + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.cancelThawCollector(users.verifier); + } + + function testPaused_RevertWhen_RevokeCollector(uint256 tokens) public useGateway useCollector(tokens) usePaused(true) { + vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); + escrow.revokeCollector(users.verifier); + } +} \ No newline at end of file diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index d2561f418..f7ffdd1c6 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -7,18 +7,6 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowWithdrawTest is GraphEscrowTest { - /* - * MODIFIERS - */ - - modifier depositAndThawTokens(uint256 amount, uint256 thawAmount) { - vm.assume(thawAmount > 0); - vm.assume(amount > thawAmount); - _depositTokens(amount); - escrow.thaw(users.indexer, thawAmount); - _; - } - /* * TESTS */ From 63f6ea1ff67c2f54a6c6399e82ef44f08432bf3b Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 22 Aug 2024 16:53:40 -0300 Subject: [PATCH 182/277] fix: compute address and deploy using create2 --- packages/horizon/test/GraphBase.t.sol | 87 ++++++++++++++++++--------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index f93009d20..6236d00dd 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; import { GraphProxyAdmin } from "@graphprotocol/contracts/contracts/upgrades/GraphProxyAdmin.sol"; import { GraphProxy } from "@graphprotocol/contracts/contracts/upgrades/GraphProxy.sol"; import { Controller } from "@graphprotocol/contracts/contracts/governance/Controller.sol"; @@ -104,26 +105,44 @@ abstract contract GraphBaseTest is Utils, Constants { GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); // GraphPayments predict address - bytes32 saltPayments = keccak256("GraphPaymentsSalt"); - bytes32 paymentsHash = keccak256(bytes.concat( - vm.getCode("GraphPayments.sol:GraphPayments"), - abi.encode(address(controller), protocolPaymentCut) - )); - address predictedPaymentsAddress = vm.computeCreate2Address( - saltPayments, - paymentsHash, + bytes memory paymentsParameters = abi.encode(address(controller), protocolPaymentCut); + bytes memory paymentsBytecode = abi.encodePacked( + type(GraphPayments).creationCode, + paymentsParameters + ); + address predictedPaymentsAddress = _computeAddress( + "GraphPayments", + paymentsBytecode, users.deployer ); // PaymentsEscrow - bytes32 escrowProxySalt = keccak256("PaymentsEscrowSalt"); - bytes32 escrowProxyHash = keccak256(bytes.concat( - vm.getCode("TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy"), - abi.encode(address(controller)) - )); - address predictedEscrowProxyAddress = vm.computeCreate2Address( - escrowProxySalt, - escrowProxyHash, + bytes memory escrowImplementationParameters = abi.encode( + address(controller), + revokeCollectorThawingPeriod,withdrawEscrowThawingPeriod + ); + bytes memory escrowImplementationBytecode = abi.encodePacked( + type(PaymentsEscrow).creationCode, + escrowImplementationParameters + ); + address predictedEscrowImplementationAddress = _computeAddress( + "PaymentsEscrow", + escrowImplementationBytecode, + users.deployer + ); + + bytes memory escrowProxyParameters = abi.encode( + predictedEscrowImplementationAddress, + users.governor, + abi.encodeCall(PaymentsEscrow.initialize, ()) + ); + bytes memory escrowProxyBytecode = abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + escrowProxyParameters + ); + address predictedEscrowProxyAddress = _computeAddress( + "TransparentUpgradeableProxy", + escrowProxyBytecode, users.deployer ); @@ -149,21 +168,15 @@ abstract contract GraphBaseTest is Utils, Constants { controller.setContractProxy(keccak256("GraphProxyAdmin"), address(proxyAdmin)); resetPrank(users.deployer); - payments = new GraphPayments{salt: saltPayments}( - address(controller), - protocolPaymentCut - ); + address paymentsAddress = _deployContract("GraphPayments", paymentsBytecode); + assertEq(paymentsAddress, predictedPaymentsAddress); + payments = GraphPayments(paymentsAddress); - address escrowImplementation = address(new PaymentsEscrow(address(controller), revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod)); - address escrowProxy = address(new TransparentUpgradeableProxy{salt: escrowProxySalt}( - escrowImplementation, - users.governor, - abi.encodeCall( - PaymentsEscrow.initialize, - () - ) - )); - escrow = PaymentsEscrow(escrowProxy); + address escrowImplementationAddress = _deployContract("PaymentsEscrow", escrowImplementationBytecode); + address escrowProxyAddress = _deployContract("TransparentUpgradeableProxy", escrowProxyBytecode); + assertEq(escrowImplementationAddress, predictedEscrowImplementationAddress); + assertEq(escrowProxyAddress, predictedEscrowProxyAddress); + escrow = PaymentsEscrow(escrowProxyAddress); stakingExtension = new HorizonStakingExtension( address(controller), @@ -213,4 +226,18 @@ abstract contract GraphBaseTest is Utils, Constants { function approve(address spender, uint256 amount) internal { token.approve(spender, amount); } + + /* + * PRIVATE + */ + + function _computeAddress(string memory contractName, bytes memory bytecode, address deployer) private pure returns (address) { + bytes32 salt = keccak256(abi.encodePacked(contractName, "Salt")); + return Create2.computeAddress(salt, keccak256(bytecode), deployer); + } + + function _deployContract(string memory contractName, bytes memory bytecode) private returns (address) { + bytes32 salt = keccak256(abi.encodePacked(contractName, "Salt")); + return Create2.deploy(0, salt, bytecode); + } } \ No newline at end of file From d3f5ece36891fd6c0c75f97a9720911ef5ca748d Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 22 Aug 2024 13:55:29 -0300 Subject: [PATCH 183/277] fix: use OpenZeppelin Address to transfer ETH (OZ L-04) --- .../contracts/data-service/extensions/DataServiceRescuable.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index f321b8d22..96fae4c26 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.26; +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IDataServiceRescuable } from "../interfaces/IDataServiceRescuable.sol"; @@ -66,7 +67,7 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { function _rescueTokens(address _to, address _token, uint256 _tokens) internal { require(_tokens != 0, DataServiceRescuableCannotRescueZero()); - if (Denominations.isNativeToken(_token)) payable(_to).transfer(_tokens); + if (Denominations.isNativeToken(_token)) Address.sendValue(payable(_to), _tokens); else SafeERC20.safeTransfer(IERC20(_token), _to, _tokens); emit TokensRescued(msg.sender, _to, _tokens); From 4d25fcd44299ac6d1d4943da2d23ebfc8e8efb3b Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 22 Aug 2024 17:07:26 -0300 Subject: [PATCH 184/277] fix: approve collector now increases allowance (OZ L-05) --- .../contracts/interfaces/IPaymentsEscrow.sol | 16 ++++---- .../contracts/payments/PaymentsEscrow.sol | 5 +-- packages/horizon/test/escrow/collector.t.sol | 40 ++++++++++++++----- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index b7ed62864..d29205ded 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -158,13 +158,6 @@ interface IPaymentsEscrow { */ error PaymentsEscrowInsufficientAllowance(uint256 allowance, uint256 minAllowance); - /** - * @notice Thrown when attempting to decrease a collector's allowance - * @param current The current allowance - * @param target The target allowance - */ - error PaymentsEscrowInconsistentAllowance(uint256 current, uint256 target); - /** * @notice Thrown when the contract balance is not consistent with the collection amount * @param balanceBefore The balance before the collection @@ -173,6 +166,11 @@ interface IPaymentsEscrow { */ error PaymentsEscrowInconsistentCollection(uint256 balanceBefore, uint256 balanceAfter, uint256 tokens); + /** + * @notice Thrown when operating a zero token amount is not allowed. + */ + error PaymentsEscrowInvalidZeroTokens(); + /** * @notice Initialize the contract */ @@ -184,12 +182,12 @@ interface IPaymentsEscrow { * To reduce it the authorization must be revoked and a new one must be created. * * Requirements: - * - `allowance` must be greater than the current allowance + * - `allowance` must be greater than zero * * Emits an {AuthorizedCollector} event * * @param collector The address of the collector - * @param allowance The amount of tokens the collector is allowed to collect + * @param allowance The amount of tokens to add to the collector's allowance */ function approveCollector(address collector, uint256 allowance) external; diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 37cc1047f..00f97c093 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -85,11 +85,10 @@ contract PaymentsEscrow is * @notice See {IPaymentsEscrow-approveCollector} */ function approveCollector(address collector_, uint256 allowance) external override notPaused { + require(allowance != 0, PaymentsEscrowInvalidZeroTokens()); Collector storage collector = authorizedCollectors[msg.sender][collector_]; - require(allowance > collector.allowance, PaymentsEscrowInconsistentAllowance(collector.allowance, allowance)); - collector.authorized = true; - collector.allowance = allowance; + collector.allowance += allowance; emit AuthorizedCollector(msg.sender, collector_); } diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index 3c13b1b42..2df4711fe 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -3,28 +3,50 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { IPaymentsEscrow } from "../../contracts/interfaces/IPaymentsEscrow.sol"; + import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowCollectorTest is GraphEscrowTest { /* - * TESTS + * HELPERS */ - function testCollector_Approve(uint256 amount) public useGateway useCollector(amount) { - (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + function _approveCollector(uint256 tokens) internal { + (, uint256 beforeAllowance,) = escrow.authorizedCollectors(users.gateway, users.verifier); + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.AuthorizedCollector(users.gateway, users.verifier); + escrow.approveCollector(users.verifier, tokens); + (bool authorized, uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); assertEq(authorized, true); + assertEq(allowance - beforeAllowance, tokens); assertEq(thawEndTimestamp, 0); } - function testCollector_RevertWhen_ApprovingForSmallerAllowance( - uint256 amount, - uint256 smallerAmount + /* + * TESTS + */ + + function testCollector_Approve( + uint256 tokens, + uint256 approveSteps + ) public useGateway { + approveSteps = bound(approveSteps, 1, 100); + vm.assume(tokens > approveSteps); + + uint256 approveTokens = tokens / approveSteps; + for (uint i = 0; i < approveSteps; i++) { + _approveCollector(approveTokens); + } + } + + function testCollector_RevertWhen_ApprovingForZeroAllowance( + uint256 amount ) public useGateway useCollector(amount) { - vm.assume(smallerAmount < amount); - bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInconsistentAllowance(uint256,uint256)", amount, smallerAmount); + bytes memory expectedError = abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowInvalidZeroTokens.selector); vm.expectRevert(expectedError); - escrow.approveCollector(users.verifier, smallerAmount); + escrow.approveCollector(users.verifier, 0); } function testCollector_Thaw(uint256 amount) public useGateway useCollector(amount) { From 1c6bb317d4fce7fb1d6dfd91143a82653d926540 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 22 Aug 2024 18:04:37 -0300 Subject: [PATCH 185/277] fix: inonsistent coding style (OZ L-06) --- .../horizon/contracts/interfaces/IGraphPayments.sol | 5 ----- .../contracts/interfaces/IPaymentsEscrow.sol | 5 ----- .../horizon/contracts/payments/GraphPayments.sol | 2 +- .../horizon/contracts/payments/PaymentsEscrow.sol | 4 ++-- .../horizon/contracts/staking/HorizonStaking.sol | 4 ++-- .../contracts/staking/HorizonStakingBase.sol | 2 +- .../contracts/staking/HorizonStakingExtension.sol | 8 ++++---- .../subgraph-service/contracts/DisputeManager.sol | 2 +- .../subgraph-service/contracts/SubgraphService.sol | 13 +++++++++---- .../contracts/interfaces/IDisputeManager.sol | 8 -------- .../contracts/interfaces/ISubgraphService.sol | 8 +------- .../contracts/libraries/Attestation.sol | 3 ++- .../contracts/utilities/AllocationManager.sol | 6 +++++- 13 files changed, 28 insertions(+), 42 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 86054ad7d..565304844 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -45,11 +45,6 @@ interface IGraphPayments { */ error GraphPaymentsInsufficientTokens(uint256 tokens, uint256 minTokens); - /** - * @notice Initialize the contract - */ - function initialize() external; - /** * @notice Collects funds from a payer. * It will pay cuts to all relevant parties and forward the rest to the receiver. diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index d29205ded..23d0b496c 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -171,11 +171,6 @@ interface IPaymentsEscrow { */ error PaymentsEscrowInvalidZeroTokens(); - /** - * @notice Initialize the contract - */ - function initialize() external; - /** * @notice Authorize a collector to collect funds from the payer's escrow * @dev This function can only be used to increase the allowance of a collector. diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 0deb8d112..bfffe4c61 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -35,7 +35,7 @@ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, I } /** - * @notice See {IGraphPayments-initialize} + * @notice Initialize the contract */ function initialize() external initializer { __Multicall_init(); diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 00f97c093..9131188bd 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -75,9 +75,9 @@ contract PaymentsEscrow is /** - * @notice See {PaymentsEscrow.initialize} + * @notice Initialize the contract */ - function initialize() external override initializer { + function initialize() external initializer { __Multicall_init(); } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index b7f20bf43..9bb05bc74 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -265,6 +265,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokens, uint256 minSharesOut ) external override notPaused { + require(tokens != 0, HorizonStakingInvalidZeroTokens()); _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, verifier, tokens, minSharesOut); } @@ -325,6 +326,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice See {IHorizonStakingMain-delegate}. */ function delegate(address serviceProvider, uint256 tokens) external override notPaused { + require(tokens != 0, HorizonStakingInvalidZeroTokens()); _graphToken().pullTokens(msg.sender, tokens); _delegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, tokens, 0); } @@ -711,8 +713,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * have been done before calling this function. */ function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) private { - require(_tokens != 0, HorizonStakingInvalidZeroTokens()); - // TODO: remove this after L2 transfer tool for delegation is removed require(_tokens >= MIN_DELEGATION, HorizonStakingInsufficientTokens(_tokens, MIN_DELEGATION)); require( diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index f62e593b1..575112e24 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -273,7 +273,7 @@ abstract contract HorizonStakingBase is address _serviceProvider, address _verifier ) internal view returns (DelegationPoolInternal storage) { - IHorizonStakingTypes.DelegationPoolInternal storage pool; + DelegationPoolInternal storage pool; if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { pool = _legacyDelegationPools[_serviceProvider]; } else { diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 38987944d..58c6401db 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -347,7 +347,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon IL2StakingTypes.ReceiveDelegationData memory _delegationData ) internal { // Get the delegation pool of the indexer - IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; + DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; IHorizonStakingTypes.DelegationInternal storage delegation = pool.delegators[_delegationData.delegator]; // If pool is in an invalid state, return the tokens to the delegator @@ -366,7 +366,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon // If no shares would be issued (probably a rounding issue or attack), // or if the amount is under the minimum delegation (which could be part of a rounding attack), // return the tokens to the delegator - _graphToken().transfer(_delegationData.delegator, _tokens); + _graphToken().pushTokens(_delegationData.delegator, _tokens); emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _tokens); } else { // Update the delegation pool @@ -516,7 +516,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon */ function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; - IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; + DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; if (pool.tokens > 0 && uint256(pool.__DEPRECATED_queryFeeCut).isValidPPM()) { uint256 indexerCut = uint256(pool.__DEPRECATED_queryFeeCut).mulPPM(_tokens); delegationRewards = _tokens - indexerCut; @@ -534,7 +534,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon */ function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; - IHorizonStakingTypes.DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; + DelegationPoolInternal storage pool = _legacyDelegationPools[_indexer]; if (pool.tokens > 0 && uint256(pool.__DEPRECATED_indexingRewardCut).isValidPPM()) { uint256 indexerCut = uint256(pool.__DEPRECATED_indexingRewardCut).mulPPM(_tokens); delegationRewards = _tokens - indexerCut; diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index f234057aa..350f355db 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -112,7 +112,7 @@ contract DisputeManager is uint256 disputeDeposit, uint32 fishermanRewardCut_, uint32 maxSlashingCut_ - ) external override initializer { + ) external initializer { __Ownable_init(msg.sender); __AttestationManager_init(); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index d9a9ca45c..ffff7af87 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.26; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; @@ -15,6 +16,7 @@ import { Directory } from "./utilities/Directory.sol"; import { AllocationManager } from "./utilities/AllocationManager.sol"; import { SubgraphServiceV1Storage } from "./SubgraphServiceStorage.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; @@ -34,6 +36,7 @@ contract SubgraphService is using PPMMath for uint256; using Allocation for mapping(address => Allocation.State); using Allocation for Allocation.State; + using TokenUtils for IGraphToken; /** * @notice Checks that an indexer is registered @@ -79,18 +82,20 @@ contract SubgraphService is } /** - * @notice See {ISubgraphService.initialize} + * @notice Initialize the contract * @dev The thawingPeriod and verifierCut ranges are not set here because they are variables * on the DisputeManager. We use the {ProvisionManager} overrideable getters to get the ranges. + * @param minimumProvisionTokens The minimum amount of provisioned tokens required to create an allocation + * @param maximumDelegationRatio The maximum delegation ratio allowed for an allocation */ - function initialize(uint256 minimumProvisionTokens, uint32 delegationRatio) external override initializer { + function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external initializer { __Ownable_init(msg.sender); __DataService_init(); __DataServicePausable_init(); __AllocationManager_init("SubgraphService", "1.0"); _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); - _setDelegationRatio(delegationRatio); + _setDelegationRatio(maximumDelegationRatio); } /** @@ -561,7 +566,7 @@ contract SubgraphService is _graphRewardsManager().onSubgraphSignalUpdate(subgraphDeploymentId); // Send GRT and bookkeep by calling collect() - _graphToken().transfer(address(_curation()), tokensCurators); + _graphToken().pushTokens(address(_curation()), tokensCurators); _curation().collect(subgraphDeploymentId, tokensCurators); } } diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 09b13aec4..088133e05 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -170,14 +170,6 @@ interface IDisputeManager { bytes32 subgraphDeploymentId2 ); - function initialize( - address arbitrator, - uint64 disputePeriod, - uint256 disputeDeposit, - uint32 fishermanRewardCut, - uint32 maxSlashingCut - ) external; - function setDisputePeriod(uint64 disputePeriod) external; function setArbitrator(address arbitrator) external; diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 5e82c66ed..0917e55d8 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -117,13 +117,6 @@ interface ISubgraphService is IDataServiceFees { */ error SubgraphServiceAllocationIsAltruistic(address allocationId); - /** - * @notice Initialize the contract - * @param minimumProvisionTokens The minimum amount of provisioned tokens required to create an allocation - * @param maximumDelegationRatio The maximum delegation ratio allowed for an allocation - */ - function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external; - /** * @notice Close a stale allocation * @dev This function can be permissionlessly called when the allocation is stale. @@ -141,6 +134,7 @@ interface ISubgraphService is IDataServiceFees { function closeStaleAllocation(address allocationId) external; /** + * @notice Change the amount of tokens in an allocation * @dev Requirements: * - The indexer must be registered diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index 7926ca30a..efb76388f 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -24,7 +24,6 @@ library Attestation { } /// @notice Attestation size is the sum of the receipt (96) + signature (65) - uint256 private constant ATTESTATION_SIZE_BYTES = RECEIPT_SIZE_BYTES + SIG_SIZE_BYTES; uint256 private constant RECEIPT_SIZE_BYTES = 96; uint256 private constant SIG_R_LENGTH = 32; @@ -34,6 +33,8 @@ library Attestation { uint256 private constant SIG_S_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH; uint256 private constant SIG_V_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH + SIG_S_LENGTH; uint256 private constant SIG_SIZE_BYTES = SIG_R_LENGTH + SIG_S_LENGTH + SIG_V_LENGTH; + + uint256 private constant ATTESTATION_SIZE_BYTES = RECEIPT_SIZE_BYTES + SIG_SIZE_BYTES; uint256 private constant UINT8_BYTE_LENGTH = 1; uint256 private constant BYTES32_BYTE_LENGTH = 32; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index f386c4371..60cf4630f 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -2,10 +2,13 @@ pragma solidity 0.8.26; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/GraphDirectory.sol"; import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; +import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; import { Allocation } from "../libraries/Allocation.sol"; @@ -25,6 +28,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca using Allocation for Allocation.State; using LegacyAllocation for mapping(address => LegacyAllocation.State); using PPMMath for uint256; + using TokenUtils for IGraphToken; ///@dev EIP712 typehash for allocation proof bytes32 private immutable EIP712_ALLOCATION_PROOF_TYPEHASH = @@ -305,7 +309,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca _graphToken().approve(address(_graphStaking()), tokensIndexerRewards); _graphStaking().stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); } else { - _graphToken().transfer(rewardsDestination, tokensIndexerRewards); + _graphToken().pushTokens(rewardsDestination, tokensIndexerRewards); } emit IndexingRewardsCollected( From fb5956a156c394ae4d16b373d355a8ca6d750cc0 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 23 Aug 2024 12:07:27 -0300 Subject: [PATCH 186/277] fix: missing validations (OZ L-07) --- .../contracts/interfaces/IGraphPayments.sol | 8 +++- .../internal/IHorizonStakingMain.sol | 11 ++++-- .../contracts/libraries/LinkedList.sol | 6 +++ .../contracts/payments/GraphPayments.sol | 1 + .../contracts/staking/HorizonStaking.sol | 7 ++-- .../staking/HorizonStakingExtension.sol | 1 + .../horizon/test/libraries/LinkedList.t.sol | 5 +++ .../horizon/test/payments/GraphPayments.t.sol | 13 +++++++ .../HorizonStakingShared.t.sol | 2 + .../horizon/test/staking/HorizonStaking.t.sol | 4 +- .../test/staking/delegation/delegate.t.sol | 4 +- .../test/staking/delegation/undelegate.t.sol | 2 +- .../test/staking/delegation/withdraw.t.sol | 2 +- .../test/staking/governance/governance.t.sol | 10 ++--- .../serviceProvider/serviceProvider.t.sol | 39 ++++++++++++------- .../horizon/test/staking/slash/slash.t.sol | 4 +- .../test/staking/transfer-tools/ttools.t.sol | 16 +++++++- .../contracts/SubgraphService.sol | 1 + .../contracts/interfaces/ISubgraphService.sol | 5 +++ .../subgraphService/provider/register.t.sol | 16 ++++++++ 20 files changed, 120 insertions(+), 37 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index 565304844..ab89c94f8 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -39,12 +39,18 @@ interface IGraphPayments { ); /** - * @notice Emitted when there are insufficient tokens to pay the required amount + * @notice Thrown when there are insufficient tokens to pay the required amount * @param tokens The amount of tokens available * @param minTokens The amount of tokens being collected */ error GraphPaymentsInsufficientTokens(uint256 tokens, uint256 minTokens); + /** + * @notice Thrown when the protocol payment cut is invalid + * @param protocolPaymentCut The protocol payment cut + */ + error GraphPaymentsInvalidProtocolPaymentCut(uint256 protocolPaymentCut); + /** * @notice Collects funds from a payer. * It will pay cuts to all relevant parties and forward the rest to the receiver. diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index e296f88e5..52dc62339 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -427,6 +427,12 @@ interface IHorizonStakingMain { */ error HorizonStakingCallerIsServiceProvider(); + /** + * @notice Thrown when trying to set a delegation fee cut that is not valid. + * @param feeCut The fee cut + */ + error HorizonStakingInvalidDelegationFeeCut(uint256 feeCut); + // -- Functions -- /** @@ -839,11 +845,10 @@ interface IHorizonStakingMain { function setAllowedLockedVerifier(address verifier, bool allowed) external; /** - * @notice Set the global delegation slashing flag. + * @notice Set the global delegation slashing flag to true. * @dev This function can only be called by the contract governor. - * @param enabled Whether delegation slashing is enabled or disabled. */ - function setDelegationSlashingEnabled(bool enabled) external; + function setDelegationSlashingEnabled() external; /** * @notice Clear the legacy global thawing period. diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index 27a22a08f..5b15d3d86 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -53,6 +53,11 @@ library LinkedList { */ error LinkedListInvalidIterations(); + /** + * @notice Thrown when trying to add an item with id equal to bytes32(0) + */ + error LinkedListInvalidZeroId(); + /** * @notice Adds an item to the list. * The item is added to the end of the list. @@ -65,6 +70,7 @@ library LinkedList { */ function addTail(List storage self, bytes32 id) internal { require(self.count < MAX_ITEMS, LinkedListMaxElementsExceeded()); + require(id != bytes32(0), LinkedListInvalidZeroId()); self.tail = id; self.nonce += 1; if (self.count == 0) self.head = id; diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index bfffe4c61..4072c2616 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -30,6 +30,7 @@ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, I * @param protocolPaymentCut The protocol tax in PPM */ constructor(address controller, uint256 protocolPaymentCut) GraphDirectory(controller) { + require(PPMMath.isValidPPM(protocolPaymentCut), GraphPaymentsInvalidProtocolPaymentCut(protocolPaymentCut)); PROTOCOL_PAYMENT_CUT = protocolPaymentCut; _disableInitializers(); } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 9bb05bc74..e6cc98315 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -318,6 +318,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { IGraphPayments.PaymentTypes paymentType, uint256 feeCut ) external override notPaused onlyAuthorized(serviceProvider, verifier) { + require(PPMMath.isValidPPM(feeCut), HorizonStakingInvalidDelegationFeeCut(feeCut)); _delegationFeeCut[serviceProvider][verifier][paymentType] = feeCut; emit DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); } @@ -468,9 +469,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice See {IHorizonStakingMain-setDelegationSlashingEnabled}. */ - function setDelegationSlashingEnabled(bool enabled) external override onlyGovernor { - _delegationSlashingEnabled = enabled; - emit DelegationSlashingEnabled(enabled); + function setDelegationSlashingEnabled() external override onlyGovernor { + _delegationSlashingEnabled = true; + emit DelegationSlashingEnabled(_delegationSlashingEnabled); } /** diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 58c6401db..1f6843d53 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -346,6 +346,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon uint256 _tokens, IL2StakingTypes.ReceiveDelegationData memory _delegationData ) internal { + require(_provisions[_delegationData.indexer][SUBGRAPH_DATA_SERVICE_ADDRESS].createdAt != 0, "!provision"); // Get the delegation pool of the indexer DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; IHorizonStakingTypes.DelegationInternal storage delegation = pool.delegators[_delegationData.delegator]; diff --git a/packages/horizon/test/libraries/LinkedList.t.sol b/packages/horizon/test/libraries/LinkedList.t.sol index d2cf60aef..5150b6116 100644 --- a/packages/horizon/test/libraries/LinkedList.t.sol +++ b/packages/horizon/test/libraries/LinkedList.t.sol @@ -14,6 +14,11 @@ contract LinkedListTest is Test, ListImplementation { list = LinkedList.List({head: bytes32(0), tail: bytes32(0), nonce: 0, count: 0}); } + function test_Add_RevertGiven_TheItemIdIsZero() external { + vm.expectRevert(LinkedList.LinkedListInvalidZeroId.selector); + list.addTail(bytes32(0)); + } + function test_Add_GivenTheListIsEmpty() external { _assert_addItem(_buildItemId(list.nonce), 0); } diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 0a53f5e20..9d2ef7495 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; +import { GraphPayments } from "../../contracts/payments/GraphPayments.sol"; import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; @@ -13,6 +14,18 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { * TESTS */ + function testConstructor_RevertIf_InvalidProtocolPaymentCut(uint256 protocolPaymentCut) public { + protocolPaymentCut = bound(protocolPaymentCut, MAX_PPM + 1, MAX_PPM + 100); + + resetPrank(users.deployer); + bytes memory expectedError = abi.encodeWithSelector( + IGraphPayments.GraphPaymentsInvalidProtocolPaymentCut.selector, + protocolPaymentCut + ); + vm.expectRevert(expectedError); + new GraphPayments(address(controller), protocolPaymentCut); + } + function testCollect( uint256 amount, uint256 tokensDataService diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 9a30f53cc..faf7b8039 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -77,5 +77,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { function _setDelegationFeeCut(IGraphPayments.PaymentTypes paymentType, uint256 cut) internal { staking.setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, cut); + uint256 delegationFeeCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType); + assertEq(delegationFeeCut, cut); } } diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index 75d23948d..1973f8581 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -80,11 +80,11 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { _; } - modifier useDelegationSlashing(bool enabled) { + modifier useDelegationSlashing() { address msgSender; (, msgSender, ) = vm.readCallers(); resetPrank(users.governor); - staking.setDelegationSlashingEnabled(enabled); + staking.setDelegationSlashingEnabled(); resetPrank(msgSender); _; } diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 79443f96c..87416daf5 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -87,7 +87,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { function testDelegate_RevertWhen_InvalidPool( uint256 tokens, uint256 delegationTokens - ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); @@ -108,7 +108,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { function testDelegate_RevertWhen_ThawingShares_InvalidPool( uint256 tokens, uint256 delegationTokens - ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 54e16d084..d256d8502 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -116,7 +116,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { function testUndelegate_RevertWhen_InvalidPool( uint256 tokens, uint256 delegationTokens - ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing(true) { + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index dc7785ed4..7eb6db57e 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -180,7 +180,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { function testWithdrawDelegation_RevertWhen_InvalidPool( uint256 tokens, uint256 delegationTokens - ) public useIndexer useProvision(tokens, 0, MAX_THAWING_PERIOD) useDelegationSlashing(true) { + ) public useIndexer useProvision(tokens, 0, MAX_THAWING_PERIOD) useDelegationSlashing() { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); diff --git a/packages/horizon/test/staking/governance/governance.t.sol b/packages/horizon/test/staking/governance/governance.t.sol index 71cd1bb49..932e053c4 100644 --- a/packages/horizon/test/staking/governance/governance.t.sol +++ b/packages/horizon/test/staking/governance/governance.t.sol @@ -31,15 +31,15 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); } - function testGovernance_SetDelgationSlashing(bool enabled) public useGovernor { - staking.setDelegationSlashingEnabled(enabled); - assertEq(staking.isDelegationSlashingEnabled(), enabled); + function testGovernance_SetDelgationSlashingEnabled() public useGovernor { + staking.setDelegationSlashingEnabled(); + assertTrue(staking.isDelegationSlashingEnabled()); } - function testGovernance_SetDelgationSlashing_NotGovernor(bool enabled) public useIndexer { + function testGovernance_SetDelgationSlashing_NotGovernor() public useIndexer { bytes memory expectedError = abi.encodeWithSignature("ManagedOnlyGovernor()"); vm.expectRevert(expectedError); - staking.setDelegationSlashingEnabled(enabled); + staking.setDelegationSlashingEnabled(); } function testGovernance_ClearThawingPeriod(uint32 thawingPeriod) public useGovernor { diff --git a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol index 5461698e3..2d32fa9e2 100644 --- a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol +++ b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol @@ -3,9 +3,11 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { HorizonStakingTest } from "../HorizonStaking.t.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + contract HorizonStakingServiceProviderTest is HorizonStakingTest { /* @@ -31,21 +33,14 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { assertEq(sp.tokensProvisioned, amount); } - function testServiceProvider_GetDelegationFeeCut( - uint256 queryCut, - uint256 indexingCut, - uint256 rewardsCut + function testServiceProvider_SetDelegationFeeCut( + uint256 feeCut, + uint8 paymentTypeInput ) public useIndexer { - _setDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, queryCut); - _setDelegationFeeCut(IGraphPayments.PaymentTypes.IndexingFee, indexingCut); - _setDelegationFeeCut(IGraphPayments.PaymentTypes.IndexingRewards, rewardsCut); - - uint256 queryFeeCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, IGraphPayments.PaymentTypes.QueryFee); - uint256 indexingFeeCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, IGraphPayments.PaymentTypes.IndexingFee); - uint256 indexingRewardsCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, IGraphPayments.PaymentTypes.IndexingRewards); - assertEq(queryFeeCut, queryCut); - assertEq(indexingFeeCut, indexingCut); - assertEq(indexingRewardsCut, rewardsCut); + vm.assume(paymentTypeInput < 3); + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes(paymentTypeInput); + feeCut = bound(feeCut, 0, MAX_PPM); + _setDelegationFeeCut(paymentType, feeCut); } function testServiceProvider_GetProvision( @@ -136,4 +131,18 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { staking.unstake(amount); assertEq(staking.getIndexerStakedTokens(users.indexer), 0); } + + function testServiceProvider_RevertIf_InvalidDelegationFeeCut( + uint256 cut, + uint8 paymentTypeInput + ) public useIndexer { + vm.assume(paymentTypeInput < 3); + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes(paymentTypeInput); + cut = bound(cut, MAX_PPM + 1, MAX_PPM + 100); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationFeeCut.selector, + cut + )); + staking.setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, cut); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index b535295fa..b68794604 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -61,7 +61,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 slashTokens, uint256 verifierCutAmount, uint256 delegationTokens - ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(false) { + ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) { vm.assume(slashTokens > tokens); delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); @@ -80,7 +80,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 slashTokens, uint256 verifierCutAmount, uint256 delegationTokens - ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing(true) { + ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing() { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); slashTokens = bound(slashTokens, tokens + 1, tokens + delegationTokens); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); diff --git a/packages/horizon/test/staking/transfer-tools/ttools.t.sol b/packages/horizon/test/staking/transfer-tools/ttools.t.sol index 28bc11264..c41731e10 100644 --- a/packages/horizon/test/staking/transfer-tools/ttools.t.sol +++ b/packages/horizon/test/staking/transfer-tools/ttools.t.sol @@ -44,6 +44,18 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { staking.onTokenTransfer(counterpartStaking, 0, data); } + function testOnTransfer_RevertWhen_ProvisionNotFound(uint256 amount) public { + amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); + + resetPrank(graphTokenGatewayAddress); + bytes memory data = abi.encode( + uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), + abi.encode(users.indexer, users.delegator) + ); + vm.expectRevert(bytes("!provision")); + staking.onTokenTransfer(counterpartStaking, amount, data); + } + function testOnTransfer_ReceiveDelegation_RevertWhen_InvalidData() public { resetPrank(graphTokenGatewayAddress); @@ -101,7 +113,7 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); } - function testOnTransfer_ReceiveDelegation_WhenInvalidPool(uint256 amount) public useDelegationSlashing(true) { + function testOnTransfer_ReceiveDelegation_WhenInvalidPool(uint256 amount) public useDelegationSlashing() { amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); uint256 originalDelegationAmount = 10 ether; uint256 provisionSize = 100 ether; @@ -196,7 +208,7 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { vm.expectEmit(); emit IHorizonStakingExtension.StakeDelegated(serviceProvider, delegator, tokens, calcShares); } - staking.onTokenTransfer(counterpartStaking, tokens, data); + staking.onTokenTransfer(from, tokens, data); // after DelegationPool memory afterPool = staking.getDelegationPool(serviceProvider, subgraphDataServiceLegacyAddress); diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index ffff7af87..fb4612964 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -126,6 +126,7 @@ contract SubgraphService is ); require(bytes(url).length > 0, SubgraphServiceEmptyUrl()); + require(bytes(geohash).length > 0, SubgraphServiceEmptyGeohash()); require(indexers[indexer].registeredAt == 0, SubgraphServiceIndexerAlreadyRegistered()); // Register the indexer diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 0917e55d8..7cb528775 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -57,6 +57,11 @@ interface ISubgraphService is IDataServiceFees { */ error SubgraphServiceEmptyUrl(); + /** + * @notice Thrown when an indexer tries to register with an empty geohash + */ + error SubgraphServiceEmptyGeohash(); + /** * @notice Thrown when an indexer tries to register but they are already registered */ diff --git a/packages/subgraph-service/test/subgraphService/provider/register.t.sol b/packages/subgraph-service/test/subgraphService/provider/register.t.sol index 2605d9e00..e42e152f7 100644 --- a/packages/subgraph-service/test/subgraphService/provider/register.t.sol +++ b/packages/subgraph-service/test/subgraphService/provider/register.t.sol @@ -72,4 +72,20 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { )); _registerIndexer(address(0)); } + + function testRegister_RevertIf_EmptyUrl(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + _createProvision(tokens); + bytes memory data = abi.encode("", "geoHash", users.rewardsDestination); + vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceEmptyUrl.selector)); + subgraphService.register(users.indexer, data); + } + + function testRegister_RevertIf_EmptyGeohash(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + _createProvision(tokens); + bytes memory data = abi.encode("url", "", users.rewardsDestination); + vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceEmptyGeohash.selector)); + subgraphService.register(users.indexer, data); + } } From 2a131ca23da6f8b731c2d260b1e3e931cadc9f12 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 23 Aug 2024 14:03:47 -0300 Subject: [PATCH 187/277] fix: missing or incorrect documentation (OZ L-08) --- .../contracts/interfaces/internal/IHorizonStakingMain.sol | 8 ++++---- .../interfaces/internal/IHorizonStakingTypes.sol | 4 ++-- packages/horizon/contracts/libraries/PPMMath.sol | 4 +++- .../subgraph-service/contracts/libraries/Allocation.sol | 2 +- .../subgraph-service/contracts/libraries/Attestation.sol | 3 +++ 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 52dc62339..bbbfa07b6 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -514,9 +514,10 @@ interface IHorizonStakingMain { * This function can be called by the service provider or by an operator authorized by the provider * for this specific verifier. * @dev Requirements: - * - `tokens` cannot be zero and must be over the data service minimum required. - * - Provision parameters must be within the range allowed by the verifier (`maxVerifierCut` and `thawingPeriod`) + * - `tokens` cannot be zero. * - The `serviceProvider` must have enough idle stake to cover the tokens to provision. + * - `maxVerifierCut` must be less than or equal to `MAX_MAX_VERIFIER_CUT`. + * - `thawingPeriod` must be less than or equal to `_maxThawingPeriod`. * * Emits a {ProvisionCreated} event. * @@ -688,7 +689,6 @@ interface IHorizonStakingMain { * - Then after the thawing period, the tokens are removed from the provision using {withdrawDelegated}. * * Requirements: - * - Must have previously initiated a thaw request using {undelegate}. * - `shares` cannot be zero. * * Emits a {TokensUndelegated} and {ThawRequestCreated} event. @@ -822,7 +822,7 @@ interface IHorizonStakingMain { ) external; /** - * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. + * @notice Authorize or unauthorize an address to be an operator for the caller on a verifier. * * @dev See {setOperator}. * Additional requirements: diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index c0d6892b3..5c2f3f5e7 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -85,9 +85,9 @@ interface IHorizonStakingTypes { struct DelegationPoolInternal { // (Deprecated) Time, in blocks, an indexer must wait before updating delegation parameters uint32 __DEPRECATED_cooldownBlocks; - // (Deprecated) Percentage of indexing rewards for the delegation pool, in PPM + // (Deprecated) Percentage of indexing rewards for the service provider, in PPM uint32 __DEPRECATED_indexingRewardCut; - // (Deprecated) Percentage of query fees for the delegation pool, in PPM + // (Deprecated) Percentage of query fees for the service provider, in PPM uint32 __DEPRECATED_queryFeeCut; // (Deprecated) Block when the delegation parameters were last updated uint256 __DEPRECATED_updatedAtBlock; diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index 1496be4d8..e992e8831 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -34,7 +34,9 @@ library PPMMath { } /** - * @notice Multiplies two values, one of which must be in PPM, and rounds up the result. + * @notice Multiplies two values, the second one must be in PPM, and rounds up the result. + * @dev requirements: + * - The second value must be in PPM. * @param a The first value. * @param b The second value. */ diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index d8f08d6d6..e039b75bd 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -193,7 +193,7 @@ library Allocation { } /** - * @notice Checks if an allocation is closed + * @notice Checks if an allocation is alturistic * @param self The allocation */ function isAltruistic(State memory self) internal pure returns (bool) { diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index efb76388f..587fadca7 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -96,6 +96,9 @@ library Attestation { // solhint-disable-next-line no-inline-assembly assembly { + // Load the 32-byte word from memory starting at `_bytes + _start + 1` + // The `0x1` accounts for the fact that we want only the first byte (uint8) + // of the loaded 32 bytes. tempUint := mload(add(add(_bytes, 0x1), _start)) } From 74368716a0da44d7adfa8188e07499953904292c Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 23 Aug 2024 15:48:51 -0300 Subject: [PATCH 188/277] fix: gas inefficiencies (OZ L-09) --- .../contracts/governance/Pausable.sol | 2 +- .../contracts/interfaces/IPaymentsEscrow.sol | 13 +--- .../contracts/libraries/LinkedList.sol | 13 ++-- .../horizon/contracts/libraries/PPMMath.sol | 2 +- .../contracts/payments/PaymentsEscrow.sol | 4 +- .../contracts/staking/HorizonStakingBase.sol | 6 +- packages/horizon/test/escrow/collect.t.sol | 11 +++- packages/horizon/test/escrow/collector.t.sol | 64 ++++++++++++------- packages/horizon/test/escrow/thaw.t.sol | 7 +- .../contracts/DisputeManager.sol | 20 +++--- .../contracts/SubgraphService.sol | 17 ----- 11 files changed, 79 insertions(+), 80 deletions(-) diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 8564b9c09..260d658af 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -66,6 +66,6 @@ abstract contract Pausable { function _setPauseGuardian(address newPauseGuardian) internal { address oldPauseGuardian = pauseGuardian; pauseGuardian = newPauseGuardian; - emit NewPauseGuardian(oldPauseGuardian, pauseGuardian); + emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian); } } diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 23d0b496c..7ab5ff023 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -28,8 +28,6 @@ interface IPaymentsEscrow { /// @notice Details for a payer-collector pair /// @dev Collectors can be removed only after a thawing period struct Collector { - // Whether the collector is authorized to collect funds - bool authorized; // Amount of tokens the collector is allowed to collect uint256 allowance; // Timestamp at which the collector thawing period ends (zero if not thawing) @@ -83,15 +81,13 @@ interface IPaymentsEscrow { * @notice Emitted when a payer thaws funds from the escrow for a payer-receiver pair * @param payer The address of the payer * @param receiver The address of the receiver - * @param tokens The amount of tokens thawed - * @param totalTokensThawing The total amount of tokens being thawed + * @param tokens The amount of tokens being thawed * @param thawEndTimestamp The timestamp at which the thawing period ends */ event Thaw( address indexed payer, address indexed receiver, uint256 tokens, - uint256 totalTokensThawing, uint256 thawEndTimestamp ); @@ -144,13 +140,6 @@ interface IPaymentsEscrow { */ error PaymentsEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); - /** - * @notice Thrown when a collector is not authorized to collect funds - * @param payer The address of the payer - * @param collector The amount of tokens the collector is allowed to collect - */ - error PaymentsEscrowCollectorNotAuthorized(address payer, address collector); - /** * @notice Thrown when a collector has insufficient allowance to collect funds * @param allowance The current allowance diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index 5b15d3d86..13607e257 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -127,23 +127,22 @@ library LinkedList { require(iterations <= self.count, LinkedListInvalidIterations()); uint256 itemCount = 0; - bool traverseAll = iterations == 0; - bytes memory acc = processInitAcc; + iterations = (iterations == 0) ? self.count : iterations; bytes32 cursor = self.head; - while (cursor != bytes32(0) && (traverseAll || iterations > 0)) { - (bool shouldBreak, bytes memory acc_) = processItem(cursor, acc); + while (cursor != bytes32(0) && iterations > 0) { + (bool shouldBreak, bytes memory acc_) = processItem(cursor, processInitAcc); if (shouldBreak) break; - acc = acc_; + processInitAcc = acc_; cursor = self.removeHead(getNextItem, deleteItem); - if (!traverseAll) iterations--; + iterations--; itemCount++; } - return (itemCount, acc); + return (itemCount, processInitAcc); } } diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index e992e8831..b02230628 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -51,6 +51,6 @@ library PPMMath { * @param value The value to check. */ function isValidPPM(uint256 value) internal pure returns (bool) { - return value >= 0 && value <= MAX_PPM; + return value <= MAX_PPM; } } diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 9131188bd..5045be86d 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -87,7 +87,6 @@ contract PaymentsEscrow is function approveCollector(address collector_, uint256 allowance) external override notPaused { require(allowance != 0, PaymentsEscrowInvalidZeroTokens()); Collector storage collector = authorizedCollectors[msg.sender][collector_]; - collector.authorized = true; collector.allowance += allowance; emit AuthorizedCollector(msg.sender, collector_); } @@ -164,7 +163,7 @@ contract PaymentsEscrow is account.tokensThawing = tokens; account.thawEndTimestamp = block.timestamp + WITHDRAW_ESCROW_THAWING_PERIOD; - emit Thaw(msg.sender, receiver, tokens, account.tokensThawing, account.thawEndTimestamp); + emit Thaw(msg.sender, receiver, tokens, account.thawEndTimestamp); } /** @@ -201,7 +200,6 @@ contract PaymentsEscrow is ) external override notPaused { // Check if collector is authorized and has enough funds Collector storage collector = authorizedCollectors[payer][msg.sender]; - require(collector.authorized, PaymentsEscrowCollectorNotAuthorized(payer, msg.sender)); require(collector.allowance >= tokens, PaymentsEscrowInsufficientAllowance(collector.allowance, tokens)); // Check if there are enough funds in the escrow account diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 575112e24..722a2f061 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -273,13 +273,11 @@ abstract contract HorizonStakingBase is address _serviceProvider, address _verifier ) internal view returns (DelegationPoolInternal storage) { - DelegationPoolInternal storage pool; if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { - pool = _legacyDelegationPools[_serviceProvider]; + return _legacyDelegationPools[_serviceProvider]; } else { - pool = _delegationPools[_serviceProvider][_verifier]; + return _delegationPools[_serviceProvider][_verifier]; } - return pool; } /** diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index baa1de06e..1ba403a23 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -3,8 +3,10 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { GraphEscrowTest } from "./GraphEscrow.t.sol"; import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; +import { IPaymentsEscrow } from "../../contracts/interfaces/IPaymentsEscrow.sol"; + +import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowCollectTest is GraphEscrowTest { @@ -35,9 +37,14 @@ contract GraphEscrowCollectTest is GraphEscrowTest { } function testCollect_RevertWhen_CollectorNotAuthorized(uint256 amount) public { + vm.assume(amount > 0); vm.startPrank(users.verifier); uint256 dataServiceCut = 30000; // 3% - bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowCollectorNotAuthorized(address,address)", users.gateway, users.verifier); + bytes memory expectedError = abi.encodeWithSelector( + IPaymentsEscrow.PaymentsEscrowInsufficientAllowance.selector, + 0, + amount + ); vm.expectRevert(expectedError); escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, dataServiceCut); vm.stopPrank(); diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index 2df4711fe..5023c38ce 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -14,16 +14,48 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { */ function _approveCollector(uint256 tokens) internal { - (, uint256 beforeAllowance,) = escrow.authorizedCollectors(users.gateway, users.verifier); + (uint256 beforeAllowance,) = escrow.authorizedCollectors(users.gateway, users.verifier); vm.expectEmit(address(escrow)); emit IPaymentsEscrow.AuthorizedCollector(users.gateway, users.verifier); escrow.approveCollector(users.verifier, tokens); - (bool authorized, uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); + (uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); assertEq(allowance - beforeAllowance, tokens); assertEq(thawEndTimestamp, 0); } + function _thawCollector() internal { + (uint256 beforeAllowance,) = escrow.authorizedCollectors(users.gateway, users.verifier); + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.ThawCollector(users.gateway, users.verifier); + escrow.thawCollector(users.verifier); + + (uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(allowance, beforeAllowance); + assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + } + + function _cancelThawCollector() internal { + (uint256 beforeAllowance, uint256 beforeThawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertTrue(beforeThawEndTimestamp != 0, "Collector should be thawing"); + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.CancelThawCollector(users.gateway, users.verifier); + escrow.cancelThawCollector(users.verifier); + + (uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(allowance, beforeAllowance); + assertEq(thawEndTimestamp, 0); + } + + function _revokeCollector() internal { + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.RevokeCollector(users.gateway, users.verifier); + escrow.revokeCollector(users.verifier); + + (uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); + assertEq(allowance, 0); + assertEq(thawEndTimestamp, 0); + } + /* * TESTS */ @@ -50,25 +82,12 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { } function testCollector_Thaw(uint256 amount) public useGateway useCollector(amount) { - escrow.thawCollector(users.verifier); - - (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); - assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); + _thawCollector(); } function testCollector_CancelThaw(uint256 amount) public useGateway useCollector(amount) { - escrow.thawCollector(users.verifier); - - (bool authorized,, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); - assertEq(thawEndTimestamp, block.timestamp + revokeCollectorThawingPeriod); - - escrow.cancelThawCollector(users.verifier); - - (authorized,, thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, true); - assertEq(thawEndTimestamp, 0); + _thawCollector(); + _cancelThawCollector(); } function testCollector_RevertWhen_CancelThawIsNotThawing(uint256 amount) public useGateway useCollector(amount) { @@ -79,12 +98,9 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { } function testCollector_Revoke(uint256 amount) public useGateway useCollector(amount) { - escrow.thawCollector(users.verifier); + _thawCollector(); skip(revokeCollectorThawingPeriod + 1); - escrow.revokeCollector(users.verifier); - - (bool authorized,,) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(authorized, false); + _revokeCollector(); } function testCollector_RevertWhen_RevokeIsNotThawing(uint256 amount) public useGateway useCollector(amount) { diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 60bf343e0..35f501ff3 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; +import { IPaymentsEscrow } from "../../contracts/interfaces/IPaymentsEscrow.sol"; + import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowThawTest is GraphEscrowTest { @@ -12,11 +14,14 @@ contract GraphEscrowThawTest is GraphEscrowTest { */ function testThaw_Tokens(uint256 amount) public useGateway useDeposit(amount) { + uint256 expectedThawEndTimestamp = block.timestamp + withdrawEscrowThawingPeriod; + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.Thaw(users.gateway, users.indexer, amount, expectedThawEndTimestamp); escrow.thaw(users.indexer, amount); (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.indexer); assertEq(amountThawing, amount); - assertEq(thawEndTimestamp, block.timestamp + withdrawEscrowThawingPeriod); + assertEq(thawEndTimestamp, expectedThawEndTimestamp); } function testThaw_RevertWhen_InsufficientThawAmount( diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 350f355db..4a40b3590 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -260,8 +260,10 @@ contract DisputeManager is function drawDispute(bytes32 disputeId) external override onlyArbitrator onlyPendingDispute(disputeId) { Dispute storage dispute = disputes[disputeId]; - // Return deposit to the fisherman - _graphToken().pushTokens(dispute.fisherman, dispute.deposit); + // Return deposit to the fisherman if any + if (dispute.deposit > 0) { + _graphToken().pushTokens(dispute.fisherman, dispute.deposit); + } // resolve related dispute if any _drawDisputeInConflict(dispute); @@ -284,8 +286,10 @@ contract DisputeManager is // Check if dispute period has finished require(dispute.createdAt + disputePeriod < block.timestamp, DisputeManagerDisputePeriodNotFinished()); - // Return deposit to the fisherman - _graphToken().pushTokens(dispute.fisherman, dispute.deposit); + // Return deposit to the fisherman if any + if (dispute.deposit > 0) { + _graphToken().pushTokens(dispute.fisherman, dispute.deposit); + } // resolve related dispute if any _cancelDisputeInConflict(dispute); @@ -633,7 +637,7 @@ contract DisputeManager is function _setArbitrator(address _arbitrator) private { require(_arbitrator != address(0), DisputeManagerInvalidZeroAddress()); arbitrator = _arbitrator; - emit ArbitratorSet(arbitrator); + emit ArbitratorSet(_arbitrator); } /** @@ -644,7 +648,7 @@ contract DisputeManager is function _setDisputePeriod(uint64 _disputePeriod) private { require(_disputePeriod != 0, DisputeManagerDisputePeriodZero()); disputePeriod = _disputePeriod; - emit DisputePeriodSet(disputePeriod); + emit DisputePeriodSet(_disputePeriod); } /** @@ -655,7 +659,7 @@ contract DisputeManager is function _setDisputeDeposit(uint256 _disputeDeposit) private { require(_disputeDeposit != 0, DisputeManagerInvalidDisputeDeposit(_disputeDeposit)); disputeDeposit = _disputeDeposit; - emit DisputeDepositSet(disputeDeposit); + emit DisputeDepositSet(_disputeDeposit); } /** @@ -666,7 +670,7 @@ contract DisputeManager is function _setFishermanRewardCut(uint32 _fishermanRewardCut) private { require(_fishermanRewardCut <= MAX_FISHERMAN_REWARD_CUT, DisputeManagerInvalidFishermanReward(_fishermanRewardCut)); fishermanRewardCut = _fishermanRewardCut; - emit FishermanRewardCutSet(fishermanRewardCut); + emit FishermanRewardCutSet(_fishermanRewardCut); } /** diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index fb4612964..c06476ec3 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -47,23 +47,6 @@ contract SubgraphService is _; } - /** - * @notice Checks that a provision is valid - * @dev A valid provision is defined as one that: - * - has at least the minimum amount of tokens requiered by the subgraph service - * - has a thawing period at least equal to {DisputeManager.disputePeriod} - * - has a verifier cut at most equal to {DisputeManager.verifierCut} - * - * Note that no delegation ratio is enforced here. - * - * @param indexer The address of the indexer - */ - modifier onlyValidProvision(address indexer) override { - _checkProvisionTokens(indexer); - _checkProvisionParameters(indexer, false); - _; - } - /** * @notice Constructor for the SubgraphService contract * @dev DataService and Directory constructors set a bunch of immutable variables From aa04aa8fb711fe85a37d994f0c2ce1132d483ffd Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 23 Aug 2024 16:22:53 -0300 Subject: [PATCH 189/277] fix: allow slashing even if SubgraphService is paused (OZ CR-01) --- packages/subgraph-service/contracts/SubgraphService.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index c06476ec3..c9741d7e2 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -290,7 +290,7 @@ contract SubgraphService is * - uint256 `tokens`: The amount of tokens to slash * - uint256 `reward`: The amount of tokens to reward the slasher */ - function slash(address indexer, bytes calldata data) external override onlyDisputeManager whenNotPaused { + function slash(address indexer, bytes calldata data) external override onlyDisputeManager { (uint256 tokens, uint256 reward) = abi.decode(data, (uint256, uint256)); _graphStaking().slash(indexer, tokens, reward, address(_disputeManager())); emit ServiceProviderSlashed(indexer, tokens); From 5f74009d827402e65589c8040b2039b745926c8e Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Fri, 23 Aug 2024 18:26:14 -0300 Subject: [PATCH 190/277] WIP --- .../libraries/ProvisionTracker.sol | 17 ++++++ .../contracts/SubgraphService.sol | 2 +- .../contracts/utilities/AllocationManager.sol | 60 +++++++++---------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index a95f634f8..08ac970bb 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -42,6 +42,23 @@ library ProvisionTracker { self[serviceProvider] += tokens; } + /** + * @notice Checks if a service provider has enough tokens available to lock + * @param self The provision tracker mapping + * @param graphStaking The HorizonStaking contract + * @param serviceProvider The service provider address + * @param delegationRatio A delegation ratio to limit the amount of delegation that's usable + */ + function check( + mapping(address => uint256) storage self, + IHorizonStaking graphStaking, + address serviceProvider, + uint32 delegationRatio + ) internal view returns (bool) { + uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this), delegationRatio); + return self[serviceProvider] <= tokensAvailable; + } + /** * @notice Releases tokens for a service provider * @dev Requirements: diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index c9741d7e2..51cb889f7 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -267,7 +267,7 @@ contract SubgraphService is allocations.get(allocationId).indexer == indexer, SubgraphServiceAllocationNotAuthorized(indexer, allocationId) ); - paymentCollected = _collectIndexingRewards(allocationId, poi); + paymentCollected = _collectIndexingRewards(allocationId, poi, delegationRatio); } else { revert SubgraphServiceInvalidPaymentType(paymentType); } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 60cf4630f..bacf67e2a 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -256,7 +256,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * @param _allocationId The id of the allocation to collect rewards for * @param _poi The POI being presented */ - function _collectIndexingRewards(address _allocationId, bytes32 _poi) internal returns (uint256) { + function _collectIndexingRewards(address _allocationId, bytes32 _poi, uint32 _delegationRatio) internal returns (uint256) { Allocation.State memory allocation = allocations.get(_allocationId); require(allocation.isOpen(), AllocationManagerAllocationClosed(_allocationId)); @@ -277,39 +277,30 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca // Any pending rewards should have been collected now allocations.clearPendingRewards(_allocationId); - if (tokensRewards == 0) { - emit IndexingRewardsCollected( + uint256 tokensIndexerRewards = 0; + uint256 tokensDelegationRewards = 0; + if (tokensRewards != 0) { + // Distribute rewards to delegators + uint256 delegatorCut = _graphStaking().getDelegationFeeCut( allocation.indexer, - _allocationId, - allocation.subgraphDeploymentId, - 0, - 0, - 0, - _poi + address(this), + IGraphPayments.PaymentTypes.IndexingFee ); - return tokensRewards; - } - - // Distribute rewards to delegators - uint256 delegatorCut = _graphStaking().getDelegationFeeCut( - allocation.indexer, - address(this), - IGraphPayments.PaymentTypes.IndexingFee - ); - uint256 tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); - if (tokensDelegationRewards > 0) { - _graphToken().approve(address(_graphStaking()), tokensDelegationRewards); - _graphStaking().addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); - } - - // Distribute rewards to indexer - uint256 tokensIndexerRewards = tokensRewards - tokensDelegationRewards; - address rewardsDestination = rewardsDestination[allocation.indexer]; - if (rewardsDestination == address(0)) { - _graphToken().approve(address(_graphStaking()), tokensIndexerRewards); - _graphStaking().stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); - } else { - _graphToken().pushTokens(rewardsDestination, tokensIndexerRewards); + tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); + if (tokensDelegationRewards > 0) { + _graphToken().approve(address(_graphStaking()), tokensDelegationRewards); + _graphStaking().addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); + } + + // Distribute rewards to indexer + tokensIndexerRewards = tokensRewards - tokensDelegationRewards; + address rewardsDestination = rewardsDestination[allocation.indexer]; + if (rewardsDestination == address(0)) { + _graphToken().approve(address(_graphStaking()), tokensIndexerRewards); + _graphStaking().stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); + } else { + _graphToken().pushTokens(rewardsDestination, tokensIndexerRewards); + } } emit IndexingRewardsCollected( @@ -322,6 +313,11 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca _poi ); + // Check if the allocation is over-allocated and close it if necessary + if (!allocationProvisionTracker.check(_graphStaking(), allocation.indexer, _delegationRatio)) { + _closeAllocation(_allocationId); + } + return tokensRewards; } From 1088e2298c5036f77e61dc73c65e543864a15e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 Aug 2024 18:42:24 -0300 Subject: [PATCH 191/277] fix: close allocation when collecting rewards if over allocated (OZ CR-02) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/utilities/AllocationManager.sol | 8 +++++-- .../subgraphService/collect/collect.t.sol | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index bacf67e2a..289faa9a8 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -256,7 +256,11 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * @param _allocationId The id of the allocation to collect rewards for * @param _poi The POI being presented */ - function _collectIndexingRewards(address _allocationId, bytes32 _poi, uint32 _delegationRatio) internal returns (uint256) { + function _collectIndexingRewards( + address _allocationId, + bytes32 _poi, + uint32 _delegationRatio + ) internal returns (uint256) { Allocation.State memory allocation = allocations.get(_allocationId); require(allocation.isOpen(), AllocationManagerAllocationClosed(_allocationId)); @@ -313,7 +317,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca _poi ); - // Check if the allocation is over-allocated and close it if necessary + // Check if the indexer is over-allocated and close the allocation if necessary if (!allocationProvisionTracker.check(_graphStaking(), allocation.indexer, _delegationRatio)) { _closeAllocation(_allocationId); } diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index 07294b25a..a04b248a3 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -9,6 +9,7 @@ import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPC import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { Allocation } from "../../../contracts/libraries/Allocation.sol"; import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; @@ -16,6 +17,7 @@ import { SubgraphServiceTest } from "../SubgraphService.t.sol"; contract SubgraphServiceRegisterTest is SubgraphServiceTest { using PPMMath for uint128; using PPMMath for uint256; + using Allocation for Allocation.State; address signer; uint256 signerPrivateKey; @@ -130,6 +132,27 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { function testCollect_IndexingRewards(uint256 tokens) public useIndexer useAllocation(tokens) { _collectIndexingRewards(users.indexer, allocationID, tokens); + + Allocation.State memory afterAllocation = subgraphService.getAllocation(allocationID); + assertEq(afterAllocation.isOpen(), true); + } + + function testCollect_IndexingRewards_When_OverAllocated(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens * 2, 10_000_000_000 ether); + + // setup allocation + _createProvision(tokens); + _registerIndexer(address(0)); + _startService(tokens); + + // thaw some tokens to become over allocated + staking.thaw(users.indexer, address(subgraphService), tokens / 2); + + // this collection should close the allocation + _collectIndexingRewards(users.indexer, allocationID, tokens); + + Allocation.State memory afterAllocation = subgraphService.getAllocation(allocationID); + assertEq(afterAllocation.isOpen(), false); } function testCollect_RevertWhen_InvalidPayment(uint256 tokens) public useIndexer useAllocation(tokens) { From b71eca01198b2ec4bf4eb13e913492e0d06a0a52 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 27 Aug 2024 12:30:43 -0300 Subject: [PATCH 192/277] fix: remove old address from event (OZ C-01) --- packages/contracts/contracts/l2/curation/L2Curation.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/contracts/contracts/l2/curation/L2Curation.sol b/packages/contracts/contracts/l2/curation/L2Curation.sol index efc690bb0..3f8728d0a 100644 --- a/packages/contracts/contracts/l2/curation/L2Curation.sol +++ b/packages/contracts/contracts/l2/curation/L2Curation.sol @@ -70,7 +70,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { /** * @dev Emitted when the subgraph service is set. */ - event SubgraphServiceSet(address indexed oldSubgraphService, address indexed newSubgraphService); + event SubgraphServiceSet(address indexed newSubgraphService); /** * @dev Modifier for functions that can only be called by the GNS contract @@ -141,9 +141,8 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { * @param _subgraphService Address of the subgraph service contract */ function setSubgraphService(address _subgraphService) external override onlyGovernor { - address oldSubgraphService = subgraphService; subgraphService = _subgraphService; - emit SubgraphServiceSet(oldSubgraphService, _subgraphService); + emit SubgraphServiceSet(_subgraphService); } /** From 157bfc6cb1ad438b75151c5ab9378972bf90a7a9 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 27 Aug 2024 12:31:31 -0300 Subject: [PATCH 193/277] fix: updated variable description (OZ H-01) --- packages/contracts/contracts/rewards/IRewardsIssuer.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol index a5400a6cf..4bcfa6ea0 100644 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -10,7 +10,7 @@ interface IRewardsIssuer { * @return subgraphDeploymentId Subgraph deployment id for the allocation * @return tokens Amount of allocated tokens * @return accRewardsPerAllocatedToken Rewards snapshot - * @return accRewardsPending Tokens pending to be claimed + * @return accRewardsPending Snapshot of accumulated rewards from previous allocation resizing, pending to be claimed */ function getAllocationData( address allocationId From 99af0a69ce3ce43f2d25fa58adea0cc0eb62232e Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 27 Aug 2024 12:32:30 -0300 Subject: [PATCH 194/277] fix: update upper bound for verifierCutRange (OZ H-02) --- .../contracts/data-service/utilities/ProvisionManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 36c3f70b0..16f2d6f1e 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -226,7 +226,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa } (uint32 verifierCutMin, uint32 verifierCutMax) = _getVerifierCutRange(); - if (verifierCutMin != type(uint32).min || verifierCutMax != type(uint32).max) { + if (verifierCutMin != type(uint32).min || verifierCutMax != uint32(PPMMath.MAX_PPM)) { uint32 maxVerifierCutToCheck = _checkPending ? _provision.maxVerifierCutPending : _provision.maxVerifierCut; _checkValueInRange(maxVerifierCutToCheck, verifierCutMin, verifierCutMax, "maxVerifierCut"); } From e2ac05dc03fc2ebb42eaed892c7f03a8528cc147 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 27 Aug 2024 12:33:23 -0300 Subject: [PATCH 195/277] fix: typo (OZ H-04) --- .../subgraph-service/contracts/interfaces/ISubgraphService.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index 7cb528775..e993c5159 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -41,7 +41,7 @@ interface ISubgraphService is IDataServiceFees { event StakeToFeesRatioSet(uint256 ratio); /** - * @notice Emmited when curator cuts are set + * @notice Emitted when curator cuts are set * @param curationCut The curation cut */ event CurationCutSet(uint256 curationCut); @@ -139,7 +139,6 @@ interface ISubgraphService is IDataServiceFees { function closeStaleAllocation(address allocationId) external; /** - * @notice Change the amount of tokens in an allocation * @dev Requirements: * - The indexer must be registered From d8bce8ceaca7da496425f4bc072e6e0d9460135c Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 27 Aug 2024 12:36:38 -0300 Subject: [PATCH 196/277] fix: encode _rav.metadata as keccak256 hash (OZ H-08) --- packages/horizon/contracts/payments/collectors/TAPCollector.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index 4ba835ace..e385667c7 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -121,7 +121,7 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { _rav.serviceProvider, _rav.timestampNs, _rav.valueAggregate, - _rav.metadata + keccak256(_rav.metadata) ) ) ); From 58ba769787d320f3432afce65021e378e7e54af3 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Tue, 27 Aug 2024 12:37:58 -0300 Subject: [PATCH 197/277] fix: remove unused import (OZ L-06) --- .../subgraph-service/contracts/utilities/AllocationManager.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 289faa9a8..1a9c86928 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -8,7 +8,6 @@ import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/Graph import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; -import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; import { Allocation } from "../libraries/Allocation.sol"; From ddbc4d20586eee08ff50d5885f469ba2557a41a5 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Wed, 28 Aug 2024 09:37:25 -0300 Subject: [PATCH 198/277] fix: remove if conditions (OZ H-02) --- .../data-service/utilities/ProvisionManager.sol | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 16f2d6f1e..ef7c9bcf1 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -220,16 +220,12 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa bool _checkPending ) internal view virtual { (uint64 thawingPeriodMin, uint64 thawingPeriodMax) = _getThawingPeriodRange(); - if (thawingPeriodMin != type(uint64).min || thawingPeriodMax != type(uint64).max) { - uint64 thawingPeriodToCheck = _checkPending ? _provision.thawingPeriodPending : _provision.thawingPeriod; - _checkValueInRange(thawingPeriodToCheck, thawingPeriodMin, thawingPeriodMax, "thawingPeriod"); - } + uint64 thawingPeriodToCheck = _checkPending ? _provision.thawingPeriodPending : _provision.thawingPeriod; + _checkValueInRange(thawingPeriodToCheck, thawingPeriodMin, thawingPeriodMax, "thawingPeriod"); (uint32 verifierCutMin, uint32 verifierCutMax) = _getVerifierCutRange(); - if (verifierCutMin != type(uint32).min || verifierCutMax != uint32(PPMMath.MAX_PPM)) { - uint32 maxVerifierCutToCheck = _checkPending ? _provision.maxVerifierCutPending : _provision.maxVerifierCut; - _checkValueInRange(maxVerifierCutToCheck, verifierCutMin, verifierCutMax, "maxVerifierCut"); - } + uint32 maxVerifierCutToCheck = _checkPending ? _provision.maxVerifierCutPending : _provision.maxVerifierCut; + _checkValueInRange(maxVerifierCutToCheck, verifierCutMin, verifierCutMax, "maxVerifierCut"); } // -- getters -- From 63d2ba4b94afb1af9b267d5fef5ddacfcfe39779 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Tue, 10 Sep 2024 04:00:49 +1000 Subject: [PATCH 199/277] Subgraph Service - Unit tests (#1022) * chore: add unit tests * fix: rebase cleanup * chore: dispute manager tests fixes * chore: dispute manager test fixes * chore: refactoring subgraph service unit tests * chore: subgraph service test fixes --- .../contracts/DisputeManager.sol | 24 +- .../contracts/interfaces/IDisputeManager.sol | 15 +- .../contracts/libraries/Attestation.sol | 2 +- .../test/SubgraphBaseTest.t.sol | 6 +- .../test/disputeManager/DisputeManager.t.sol | 426 ++++++++++++++++-- .../constructor/constructor.t.sol | 20 +- .../test/disputeManager/disputes/accept.t.sol | 223 --------- .../test/disputeManager/disputes/cancel.t.sol | 70 --- .../test/disputeManager/disputes/create.t.sol | 146 ------ .../disputeManager/disputes/disputes.t.sol | 71 +++ .../test/disputeManager/disputes/draw.t.sol | 67 --- .../disputes/indexing/accept.t.sol | 64 +++ .../disputes/indexing/cancel.t.sol | 42 ++ .../disputes/indexing/create.t.sol | 111 +++++ .../disputes/indexing/draw.t.sol | 34 ++ .../disputes/indexing/reject.t.sol | 34 ++ .../disputes/query/accept.t.sol | 75 +++ .../disputes/query/cancel.t.sol | 53 +++ .../disputes/query/create.t.sol | 136 ++++++ .../disputeManager/disputes/query/draw.t.sol | 45 ++ .../disputes/query/reject.t.sol | 44 ++ .../disputes/queryConflict/accept.t.sol | 96 ++++ .../disputes/queryConflict/cancel.t.sol | 76 ++++ .../disputes/queryConflict/create.t.sol | 107 +++++ .../disputes/queryConflict/draw.t.sol | 59 +++ .../disputes/queryConflict/reject.t.sol | 42 ++ .../governance/arbitrator.t.sol | 32 ++ .../governance/disputeDeposit.t.sol | 32 ++ .../governance/fishermanRewardCut.t.sol | 7 +- .../governance/maxSlashingCut.t.sol | 32 ++ .../test/shared/HorizonStakingShared.t.sol | 75 +++ .../test/shared/SubgraphServiceShared.t.sol | 148 +++++- .../subgraphService/SubgraphService.t.sol | 335 +++++++++++++- .../subgraphService/allocate/resize.t.sol | 129 ------ .../test/subgraphService/allocate/start.t.sol | 166 ------- .../allocation/closeStale.t.sol | 108 +++++ .../subgraphService/allocation/resize.t.sol | 86 ++++ .../subgraphService/allocation/start.t.sol | 208 +++++++++ .../{allocate => allocation}/stop.t.sol | 31 +- .../subgraphService/collect/collect.t.sol | 210 +-------- .../collect/indexing/indexing.t.sol | 125 +++++ .../subgraphService/collect/query/query.t.sol | 157 +++++++ .../subgraphService/provider/register.t.sol | 51 +-- .../provider/rewardsDestination.t.sol | 26 ++ .../subgraphService/provision/accept.t.sol | 77 +++- .../subgraph-service/test/utils/Constants.sol | 3 +- 46 files changed, 2943 insertions(+), 1183 deletions(-) delete mode 100644 packages/subgraph-service/test/disputeManager/disputes/accept.t.sol delete mode 100644 packages/subgraph-service/test/disputeManager/disputes/cancel.t.sol delete mode 100644 packages/subgraph-service/test/disputeManager/disputes/create.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol delete mode 100644 packages/subgraph-service/test/disputeManager/disputes/draw.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol create mode 100644 packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol create mode 100644 packages/subgraph-service/test/shared/HorizonStakingShared.t.sol delete mode 100644 packages/subgraph-service/test/subgraphService/allocate/resize.t.sol delete mode 100644 packages/subgraph-service/test/subgraphService/allocate/start.t.sol create mode 100644 packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol create mode 100644 packages/subgraph-service/test/subgraphService/allocation/resize.t.sol create mode 100644 packages/subgraph-service/test/subgraphService/allocation/start.t.sol rename packages/subgraph-service/test/subgraphService/{allocate => allocation}/stop.t.sol (70%) create mode 100644 packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol create mode 100644 packages/subgraph-service/test/subgraphService/collect/query/query.t.sol create mode 100644 packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 4a40b3590..a9afcff28 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -128,18 +128,15 @@ contract DisputeManager is * The disputes are created in reference to an allocationId and specifically * a POI for that allocation. * This function is called by a challenger and it will pull `disputeDeposit` GRT tokens. - * + * * Requirements: - * - Challenger must have previously approved this contract to pull `disputeDeposit` amount + * - Challenger must have previously approved this contract to pull `disputeDeposit` amount * of tokens from their balance. - * + * * @param allocationId The allocation to dispute * @param poi The Proof of Indexing (POI) being disputed */ - function createIndexingDispute( - address allocationId, - bytes32 poi - ) external override returns (bytes32) { + function createIndexingDispute(address allocationId, bytes32 poi) external override returns (bytes32) { // Get funds from submitter _pullSubmitterDeposit(); @@ -150,11 +147,11 @@ contract DisputeManager is /** * @notice Create a query dispute for the arbitrator to resolve. * This function is called by a challenger and it will pull `disputeDeposit` GRT tokens. - * + * * * Requirements: - * - Challenger must have previously approved this contract to pull `disputeDeposit` amount + * - Challenger must have previously approved this contract to pull `disputeDeposit` amount * of tokens from their balance. - * + * * @param attestationData Attestation bytes submitted by the challenger */ function createQueryDispute(bytes calldata attestationData) external override returns (bytes32) { @@ -296,6 +293,8 @@ contract DisputeManager is // store dispute status dispute.status = IDisputeManager.DisputeStatus.Cancelled; + + emit DisputeCancelled(disputeId, dispute.indexer, dispute.fisherman, dispute.deposit); } /** @@ -668,7 +667,10 @@ contract DisputeManager is * @param _fishermanRewardCut Reward as a percentage of indexer stake */ function _setFishermanRewardCut(uint32 _fishermanRewardCut) private { - require(_fishermanRewardCut <= MAX_FISHERMAN_REWARD_CUT, DisputeManagerInvalidFishermanReward(_fishermanRewardCut)); + require( + _fishermanRewardCut <= MAX_FISHERMAN_REWARD_CUT, + DisputeManagerInvalidFishermanReward(_fishermanRewardCut) + ); fishermanRewardCut = _fishermanRewardCut; emit FishermanRewardCutSet(_fishermanRewardCut); } diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 088133e05..73f7e56d6 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -143,6 +143,17 @@ interface IDisputeManager { */ event DisputeLinked(bytes32 indexed disputeId1, bytes32 indexed disputeId2); + /** + * @dev Emitted when a dispute is cancelled by the fisherman. + * The event emits the amount `tokens` returned to the fisherman. + */ + event DisputeCancelled( + bytes32 indexed disputeId, + address indexed indexer, + address indexed fisherman, + uint256 tokens + ); + // -- Errors -- error DisputeManagerNotArbitrator(); @@ -213,10 +224,10 @@ interface IDisputeManager { function getAttestationIndexer(Attestation.State memory attestation) external view returns (address); + function getStakeSnapshot(address indexer) external view returns (uint256); + function areConflictingAttestations( Attestation.State memory attestation1, Attestation.State memory attestation2 ) external pure returns (bool); - - function getStakeSnapshot(address indexer) external view returns (uint256); } diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index 587fadca7..0211db674 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -33,7 +33,7 @@ library Attestation { uint256 private constant SIG_S_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH; uint256 private constant SIG_V_OFFSET = RECEIPT_SIZE_BYTES + SIG_R_LENGTH + SIG_S_LENGTH; uint256 private constant SIG_SIZE_BYTES = SIG_R_LENGTH + SIG_S_LENGTH + SIG_V_LENGTH; - + uint256 private constant ATTESTATION_SIZE_BYTES = RECEIPT_SIZE_BYTES + SIG_SIZE_BYTES; uint256 private constant UINT8_BYTE_LENGTH = 1; diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 9991ab8a5..2fe5ccf64 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -40,9 +40,9 @@ abstract contract SubgraphBaseTest is Utils, Constants { SubgraphService subgraphService; DisputeManager disputeManager; IHorizonStaking staking; - IGraphPayments graphPayments; + GraphPayments graphPayments; IPaymentsEscrow escrow; - ITAPCollector tapCollector; + TAPCollector tapCollector; HorizonStaking private stakingBase; HorizonStakingExtension private stakingExtension; @@ -196,7 +196,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { controller.setPaused(false); } - function createUser(string memory name) private returns (address) { + function createUser(string memory name) internal returns (address) { address user = makeAddr(name); vm.deal({ account: user, newBalance: 100 ether }); deal({ token: address(token), to: user, give: 10_000_000_000 ether }); diff --git a/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol b/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol index 9f80512b4..1077c1435 100644 --- a/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol +++ b/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol @@ -8,6 +8,8 @@ import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils. import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; import { Attestation } from "../../contracts/libraries/Attestation.sol"; +import { Allocation } from "../../contracts/libraries/Allocation.sol"; +import { IDisputeManager } from "../../contracts/interfaces/IDisputeManager.sol"; import { SubgraphServiceSharedTest } from "../shared/SubgraphServiceShared.t.sol"; @@ -31,73 +33,415 @@ contract DisputeManagerTest is SubgraphServiceSharedTest { } /* - * HELPERS + * ACTIONS */ - function _createIndexingDispute(address _allocationID, bytes32 _poi) internal returns (bytes32 disputeID) { - address msgSender; - (, msgSender,) = vm.readCallers(); - resetPrank(users.fisherman); - uint256 beforeFishermanBalance = token.balanceOf(users.fisherman); + function _setArbitrator(address _arbitrator) internal { + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.ArbitratorSet(_arbitrator); + disputeManager.setArbitrator(_arbitrator); + assertEq(disputeManager.arbitrator(), _arbitrator, "Arbitrator should be set."); + } + + function _setFishermanRewardCut(uint32 _fishermanRewardCut) internal { + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.FishermanRewardCutSet(_fishermanRewardCut); + disputeManager.setFishermanRewardCut(_fishermanRewardCut); + assertEq(disputeManager.fishermanRewardCut(), _fishermanRewardCut, "Fisherman reward cut should be set."); + } + + function _setMaxSlashingCut(uint32 _maxSlashingCut) internal { + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.MaxSlashingCutSet(_maxSlashingCut); + disputeManager.setMaxSlashingCut(_maxSlashingCut); + assertEq(disputeManager.maxSlashingCut(), _maxSlashingCut, "Max slashing cut should be set."); + } + + function _setDisputeDeposit(uint256 _disputeDeposit) internal { + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.DisputeDepositSet(_disputeDeposit); + disputeManager.setDisputeDeposit(_disputeDeposit); + assertEq(disputeManager.disputeDeposit(), _disputeDeposit, "Dispute deposit should be set."); + } + + function _createIndexingDispute(address _allocationId, bytes32 _poi) internal returns (bytes32) { + (, address fisherman, ) = vm.readCallers(); + bytes32 expectedDisputeId = keccak256(abi.encodePacked(_allocationId, _poi)); + uint256 disputeDeposit = disputeManager.disputeDeposit(); + uint256 beforeFishermanBalance = token.balanceOf(fisherman); + Allocation.State memory alloc = subgraphService.getAllocation(_allocationId); + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(alloc.indexer); + + // Approve the dispute deposit token.approve(address(disputeManager), disputeDeposit); - bytes32 _disputeID = disputeManager.createIndexingDispute(_allocationID, _poi); - uint256 afterFishermanBalance = token.balanceOf(users.fisherman); + + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.IndexingDisputeCreated( + expectedDisputeId, + alloc.indexer, + fisherman, + disputeDeposit, + _allocationId, + _poi, + stakeSnapshot + ); + + // Create the indexing dispute + bytes32 _disputeId = disputeManager.createIndexingDispute(_allocationId, _poi); + + // Check that the dispute was created and that it has the correct ID + assertTrue(disputeManager.isDisputeCreated(_disputeId), "Dispute should be created."); + assertEq(expectedDisputeId, _disputeId, "Dispute ID should match"); + + // Check dispute values + IDisputeManager.Dispute memory dispute = _getDispute(_disputeId); + assertEq(dispute.indexer, alloc.indexer, "Indexer should match"); + assertEq(dispute.fisherman, fisherman, "Fisherman should match"); + assertEq(dispute.deposit, disputeDeposit, "Deposit should match"); + assertEq(dispute.relatedDisputeId, bytes32(0), "Related dispute ID should be empty"); + assertEq(uint8(dispute.disputeType), uint8(IDisputeManager.DisputeType.IndexingDispute), "Dispute type should be indexing"); + assertEq(uint8(dispute.status), uint8(IDisputeManager.DisputeStatus.Pending), "Dispute status should be pending"); + assertEq(dispute.createdAt, block.timestamp, "Created at should match"); + assertEq(dispute.stakeSnapshot, stakeSnapshot, "Stake snapshot should match"); + + // Check that the fisherman was charged the dispute deposit + uint256 afterFishermanBalance = token.balanceOf(fisherman); assertEq(afterFishermanBalance, beforeFishermanBalance - disputeDeposit, "Fisherman should be charged the dispute deposit"); - resetPrank(msgSender); - return _disputeID; + + return _disputeId; } - function _createQueryDispute() internal returns (bytes32 disputeID) { - address msgSender; - (, msgSender,) = vm.readCallers(); - resetPrank(users.fisherman); - Attestation.Receipt memory receipt = Attestation.Receipt({ - requestCID: keccak256(abi.encodePacked("Request CID")), - responseCID: keccak256(abi.encodePacked("Response CID")), - subgraphDeploymentId: keccak256(abi.encodePacked("Subgraph Deployment ID")) - }); - bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + function _createQueryDispute(bytes memory _attestationData) internal returns (bytes32) { + (, address fisherman,) = vm.readCallers(); + Attestation.State memory attestation = Attestation.parse(_attestationData); + address indexer = disputeManager.getAttestationIndexer(attestation); + bytes32 expectedDisputeId = keccak256( + abi.encodePacked( + attestation.requestCID, + attestation.responseCID, + attestation.subgraphDeploymentId, + indexer, + fisherman + ) + ); + uint256 disputeDeposit = disputeManager.disputeDeposit(); + uint256 beforeFishermanBalance = token.balanceOf(fisherman); + uint256 stakeSnapshot = disputeManager.getStakeSnapshot(indexer); - uint256 beforeFishermanBalance = token.balanceOf(users.fisherman); + // Approve the dispute deposit token.approve(address(disputeManager), disputeDeposit); - bytes32 _disputeID = disputeManager.createQueryDispute(attestationData); - uint256 afterFishermanBalance = token.balanceOf(users.fisherman); + + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.QueryDisputeCreated( + expectedDisputeId, + indexer, + fisherman, + disputeDeposit, + attestation.subgraphDeploymentId, + _attestationData, + stakeSnapshot + ); + + bytes32 _disputeID = disputeManager.createQueryDispute(_attestationData); + + // Check that the dispute was created and that it has the correct ID + assertTrue(disputeManager.isDisputeCreated(_disputeID), "Dispute should be created."); + assertEq(expectedDisputeId, _disputeID, "Dispute ID should match"); + + // Check dispute values + IDisputeManager.Dispute memory dispute = _getDispute(_disputeID); + assertEq(dispute.indexer, indexer, "Indexer should match"); + assertEq(dispute.fisherman, fisherman, "Fisherman should match"); + assertEq(dispute.deposit, disputeDeposit, "Deposit should match"); + assertEq(dispute.relatedDisputeId, bytes32(0), "Related dispute ID should be empty"); + assertEq(uint8(dispute.disputeType), uint8(IDisputeManager.DisputeType.QueryDispute), "Dispute type should be query"); + assertEq(uint8(dispute.status), uint8(IDisputeManager.DisputeStatus.Pending), "Dispute status should be pending"); + assertEq(dispute.createdAt, block.timestamp, "Created at should match"); + assertEq(dispute.stakeSnapshot, stakeSnapshot, "Stake snapshot should match"); + + // Check that the fisherman was charged the dispute deposit + uint256 afterFishermanBalance = token.balanceOf(fisherman); assertEq(afterFishermanBalance, beforeFishermanBalance - disputeDeposit, "Fisherman should be charged the dispute deposit"); - resetPrank(msgSender); + return _disputeID; } + function _createQueryDisputeConflict( + bytes memory attestationData1, + bytes memory attestationData2 + ) internal returns (bytes32, bytes32) { + (, address fisherman,) = vm.readCallers(); + Attestation.State memory attestation1 = Attestation.parse(attestationData1); + Attestation.State memory attestation2 = Attestation.parse(attestationData2); + address indexer1 = disputeManager.getAttestationIndexer(attestation1); + address indexer2 = disputeManager.getAttestationIndexer(attestation2); + bytes32 expectedDisputeId1 = keccak256( + abi.encodePacked( + attestation1.requestCID, + attestation1.responseCID, + attestation1.subgraphDeploymentId, + indexer1, + fisherman + ) + ); + bytes32 expectedDisputeId2 = keccak256( + abi.encodePacked( + attestation2.requestCID, + attestation2.responseCID, + attestation2.subgraphDeploymentId, + indexer2, + fisherman + ) + ); + uint256 stakeSnapshot1 = disputeManager.getStakeSnapshot(indexer1); + uint256 stakeSnapshot2 = disputeManager.getStakeSnapshot(indexer2); + + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.QueryDisputeCreated( + expectedDisputeId1, + indexer1, + fisherman, + 0, + attestation1.subgraphDeploymentId, + attestationData1, + stakeSnapshot1 + ); + emit IDisputeManager.QueryDisputeCreated( + expectedDisputeId2, + indexer2, + fisherman, + 0, + attestation2.subgraphDeploymentId, + attestationData2, + stakeSnapshot2 + ); + + (bytes32 _disputeId1, bytes32 _disputeId2) = disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + + // Check that the disputes were created and that they have the correct IDs + assertTrue(disputeManager.isDisputeCreated(_disputeId1), "Dispute 1 should be created."); + assertTrue(disputeManager.isDisputeCreated(_disputeId2), "Dispute 2 should be created."); + assertEq(expectedDisputeId1, _disputeId1, "Dispute 1 ID should match"); + assertEq(expectedDisputeId2, _disputeId2, "Dispute 2 ID should match"); + + // Check dispute values + IDisputeManager.Dispute memory dispute1 = _getDispute(_disputeId1); + assertEq(dispute1.indexer, indexer1, "Indexer 1 should match"); + assertEq(dispute1.fisherman, fisherman, "Fisherman 1 should match"); + assertEq(dispute1.deposit, 0, "Deposit 1 should match"); + assertEq(dispute1.relatedDisputeId, _disputeId2, "Related dispute ID 1 should be the id of the other dispute"); + assertEq(uint8(dispute1.disputeType), uint8(IDisputeManager.DisputeType.QueryDispute), "Dispute type 1 should be query"); + assertEq(uint8(dispute1.status), uint8(IDisputeManager.DisputeStatus.Pending), "Dispute status 1 should be pending"); + assertEq(dispute1.createdAt, block.timestamp, "Created at 1 should match"); + assertEq(dispute1.stakeSnapshot, stakeSnapshot1, "Stake snapshot 1 should match"); + + IDisputeManager.Dispute memory dispute2 = _getDispute(_disputeId2); + assertEq(dispute2.indexer, indexer2, "Indexer 2 should match"); + assertEq(dispute2.fisherman, fisherman, "Fisherman 2 should match"); + assertEq(dispute2.deposit, 0, "Deposit 2 should match"); + assertEq(dispute2.relatedDisputeId, _disputeId1, "Related dispute ID 2 should be the id of the other dispute"); + assertEq(uint8(dispute2.disputeType), uint8(IDisputeManager.DisputeType.QueryDispute), "Dispute type 2 should be query"); + assertEq(uint8(dispute2.status), uint8(IDisputeManager.DisputeStatus.Pending), "Dispute status 2 should be pending"); + assertEq(dispute2.createdAt, block.timestamp, "Created at 2 should match"); + assertEq(dispute2.stakeSnapshot, stakeSnapshot2, "Stake snapshot 2 should match"); + + return (_disputeId1, _disputeId2); + } + + function _acceptDispute(bytes32 _disputeId, uint256 _tokensSlash) internal { + IDisputeManager.Dispute memory dispute = _getDispute(_disputeId); + address fisherman = dispute.fisherman; + uint256 fishermanPreviousBalance = token.balanceOf(fisherman); + uint256 indexerTokensAvailable = staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)); + uint256 disputeDeposit = dispute.deposit; + uint256 fishermanRewardPercentage = disputeManager.fishermanRewardCut(); + uint256 fishermanReward = _tokensSlash.mulPPM(fishermanRewardPercentage); + + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.DisputeAccepted(_disputeId, dispute.indexer, dispute.fisherman, dispute.deposit + fishermanReward); + + // Accept the dispute + disputeManager.acceptDispute(_disputeId, _tokensSlash); + + // Check fisherman's got their reward and their deposit (if any) back + uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward + disputeDeposit; + assertEq(token.balanceOf(fisherman), fishermanExpectedBalance, "Fisherman should get their reward and deposit back"); + + // Check indexer was slashed by the correct amount + uint256 expectedIndexerTokensAvailable; + if (_tokensSlash > indexerTokensAvailable) { + expectedIndexerTokensAvailable = 0; + } else { + expectedIndexerTokensAvailable = indexerTokensAvailable - _tokensSlash; + } + assertEq(staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)), expectedIndexerTokensAvailable, "Indexer should be slashed by the correct amount"); + + // Check dispute status + dispute = _getDispute(_disputeId); + assertEq(uint8(dispute.status), uint8(IDisputeManager.DisputeStatus.Accepted), "Dispute status should be accepted"); + + // If there's a related dispute, check that it was rejected + if (dispute.relatedDisputeId != bytes32(0)) { + IDisputeManager.Dispute memory relatedDispute = _getDispute(dispute.relatedDisputeId); + assertEq(uint8(relatedDispute.status), uint8(IDisputeManager.DisputeStatus.Rejected), "Related dispute status should be rejected"); + } + } + + function _drawDispute(bytes32 _disputeId) internal { + IDisputeManager.Dispute memory dispute = _getDispute(_disputeId); + address fisherman = dispute.fisherman; + uint256 fishermanPreviousBalance = token.balanceOf(fisherman); + uint256 indexerTokensAvailable = staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)); + + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.DisputeDrawn(_disputeId, dispute.indexer, dispute.fisherman, dispute.deposit); + + // Draw the dispute + disputeManager.drawDispute(_disputeId); + + // Check that the fisherman got their deposit back + uint256 fishermanExpectedBalance = fishermanPreviousBalance + dispute.deposit; + assertEq(token.balanceOf(fisherman), fishermanExpectedBalance, "Fisherman should receive their deposit back."); + + // Check that indexer was not slashed + assertEq(staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)), indexerTokensAvailable, "Indexer should not be slashed"); + + // Check dispute status + dispute = _getDispute(_disputeId); + assertEq(uint8(dispute.status), uint8(IDisputeManager.DisputeStatus.Drawn), "Dispute status should be drawn"); + + // If there's a related dispute, check that it was drawn too + if (dispute.relatedDisputeId != bytes32(0)) { + IDisputeManager.Dispute memory relatedDispute = _getDispute(dispute.relatedDisputeId); + assertEq(uint8(relatedDispute.status), uint8(IDisputeManager.DisputeStatus.Drawn), "Related dispute status should be drawn"); + } + } + + function _rejectDispute(bytes32 _disputeId) internal { + IDisputeManager.Dispute memory dispute = _getDispute(_disputeId); + address fisherman = dispute.fisherman; + uint256 fishermanPreviousBalance = token.balanceOf(fisherman); + uint256 indexerTokensAvailable = staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)); + + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.DisputeRejected(_disputeId, dispute.indexer, dispute.fisherman, dispute.deposit); + + // Reject the dispute + disputeManager.rejectDispute(_disputeId); + + // Check that the fisherman didn't get their deposit back + assertEq(token.balanceOf(users.fisherman), fishermanPreviousBalance, "Fisherman should lose the deposit."); + + // Check that indexer was not slashed + assertEq(staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)), indexerTokensAvailable, "Indexer should not be slashed"); + + // Check dispute status + dispute = _getDispute(_disputeId); + assertEq(uint8(dispute.status), uint8(IDisputeManager.DisputeStatus.Rejected), "Dispute status should be rejected"); + // Checl related id is empty + assertEq(dispute.relatedDisputeId, bytes32(0), "Related dispute ID should be empty"); + } + + function _cancelDispute(bytes32 _disputeId) internal { + IDisputeManager.Dispute memory dispute = _getDispute(_disputeId); + address fisherman = dispute.fisherman; + uint256 fishermanPreviousBalance = token.balanceOf(fisherman); + uint256 disputePeriod = disputeManager.disputePeriod(); + uint256 indexerTokensAvailable = staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)); + + // skip to end of dispute period + skip(disputePeriod + 1); + + vm.expectEmit(address(disputeManager)); + emit IDisputeManager.DisputeCancelled(_disputeId, dispute.indexer, dispute.fisherman, dispute.deposit); + + // Cancel the dispute + disputeManager.cancelDispute(_disputeId); + + // Check that the fisherman got their deposit back + uint256 fishermanExpectedBalance = fishermanPreviousBalance + dispute.deposit; + assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance, "Fisherman should receive their deposit back."); + + // Check that indexer was not slashed + assertEq(staking.getProviderTokensAvailable(dispute.indexer, address(subgraphService)), indexerTokensAvailable, "Indexer should not be slashed"); + + // Check dispute status + dispute = _getDispute(_disputeId); + assertEq(uint8(dispute.status), uint8(IDisputeManager.DisputeStatus.Cancelled), "Dispute status should be cancelled"); + + // If there's a related dispute, check that it was cancelled too + if (dispute.relatedDisputeId != bytes32(0)) { + IDisputeManager.Dispute memory relatedDispute = _getDispute(dispute.relatedDisputeId); + assertEq(uint8(relatedDispute.status), uint8(IDisputeManager.DisputeStatus.Cancelled), "Related dispute status should be cancelled"); + } + } + + /* + * HELPERS + */ + + function _createAttestationReceipt( + bytes32 requestCID, + bytes32 responseCID, + bytes32 subgraphDeploymentId + ) internal pure returns (Attestation.Receipt memory receipt) { + return Attestation.Receipt({ + requestCID: requestCID, + responseCID: responseCID, + subgraphDeploymentId: subgraphDeploymentId + }); + } + function _createConflictingAttestations( + bytes32 requestCID, + bytes32 subgraphDeploymentId, bytes32 responseCID1, - bytes32 subgraphDeploymentId1, bytes32 responseCID2, - bytes32 subgraphDeploymentId2 + uint256 signer1, + uint256 signer2 ) internal view returns (bytes memory attestationData1, bytes memory attestationData2) { - bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); - Attestation.Receipt memory receipt1 = Attestation.Receipt({ - requestCID: requestCID, - responseCID: responseCID1, - subgraphDeploymentId: subgraphDeploymentId1 - }); + Attestation.Receipt memory receipt1 = _createAttestationReceipt(requestCID, responseCID1, subgraphDeploymentId); + Attestation.Receipt memory receipt2 = _createAttestationReceipt(requestCID, responseCID2, subgraphDeploymentId); - Attestation.Receipt memory receipt2 = Attestation.Receipt({ - requestCID: requestCID, - responseCID: responseCID2, - subgraphDeploymentId: subgraphDeploymentId2 - }); - - bytes memory _attestationData1 = _createAtestationData(receipt1, allocationIDPrivateKey); - bytes memory _attestationData2 = _createAtestationData(receipt2, allocationIDPrivateKey); + bytes memory _attestationData1 = _createAtestationData(receipt1, signer1); + bytes memory _attestationData2 = _createAtestationData(receipt2, signer2); return (_attestationData1, _attestationData2); } function _createAtestationData( Attestation.Receipt memory receipt, uint256 signer - ) private view returns (bytes memory attestationData) { + ) internal view returns (bytes memory attestationData) { bytes32 digest = disputeManager.encodeReceipt(receipt); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); return abi.encodePacked(receipt.requestCID, receipt.responseCID, receipt.subgraphDeploymentId, r, s, v); } + + /* + * PRIVATE FUNCTIONS + */ + + function _getDispute(bytes32 _disputeId) internal view returns (IDisputeManager.Dispute memory) { + ( + address indexer, + address fisherman, + uint256 deposit, + bytes32 relatedDisputeId, + IDisputeManager.DisputeType disputeType, + IDisputeManager.DisputeStatus status, + uint256 createdAt, + uint256 stakeSnapshot + ) = disputeManager.disputes(_disputeId); + return IDisputeManager.Dispute({ + indexer: indexer, + fisherman: fisherman, + deposit: deposit, + relatedDisputeId: relatedDisputeId, + disputeType: disputeType, + status: status, + createdAt: createdAt, + stakeSnapshot: stakeSnapshot + }); + } } diff --git a/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol b/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol index d4f100f68..76f90481a 100644 --- a/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol +++ b/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol @@ -49,10 +49,12 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { * TESTS */ - function test_Constructor( - uint32 fishermanRewardPercentage + function test_DisputeManager_Constructor( + uint32 fishermanRewardPercentage, + uint32 maxSlashingPercentage ) public useDeployer { vm.assume(fishermanRewardPercentage <= disputeManager.MAX_FISHERMAN_REWARD_CUT()); + vm.assume(maxSlashingPercentage <= PPMMath.MAX_PPM); address disputeManagerImplementation = address(new DisputeManager(address(controller))); address proxy = _initializeDisputeManager( disputeManagerImplementation, @@ -70,7 +72,7 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { assertEq(disputeManager.fishermanRewardCut(), fishermanRewardPercentage); } - function test_Constructor_RevertIf_ControllerAddressIsZero() public useDeployer { + function test_DisputeManager_Constructor_RevertIf_ControllerAddressIsZero() public useDeployer { bytes memory expectedError = abi.encodeWithSelector( GraphDirectory.GraphDirectoryInvalidZeroAddress.selector, "Controller" @@ -79,7 +81,7 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { new DisputeManager(address(0)); } - function test_Constructor_RevertIf_ArbitratorAddressIsZero() public useDeployer { + function test_DisputeManager_Constructor_RevertIf_ArbitratorAddressIsZero() public useDeployer { address disputeManagerImplementation = address(new DisputeManager(address(controller))); bytes memory expectedError = abi.encodeWithSelector( IDisputeManager.DisputeManagerInvalidZeroAddress.selector @@ -95,7 +97,7 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { ); } - function test_Constructor_RevertIf_InvalidDisputePeriod() public useDeployer { + function test_DisputeManager_Constructor_RevertIf_InvalidDisputePeriod() public useDeployer { address disputeManagerImplementation = address(new DisputeManager(address(controller))); bytes memory expectedError = abi.encodeWithSelector( IDisputeManager.DisputeManagerDisputePeriodZero.selector @@ -111,7 +113,7 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { ); } - function test_Constructor_RevertIf_InvalidDisputeDeposit() public useDeployer { + function test_DisputeManager_Constructor_RevertIf_InvalidDisputeDeposit() public useDeployer { address disputeManagerImplementation = address(new DisputeManager(address(controller))); bytes memory expectedError = abi.encodeWithSelector( IDisputeManager.DisputeManagerInvalidDisputeDeposit.selector, @@ -128,7 +130,7 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { ); } - function test_Constructor_RevertIf_InvalidFishermanRewardPercentage(uint32 _fishermanRewardPercentage) public useDeployer { + function test_DisputeManager_Constructor_RevertIf_InvalidFishermanRewardPercentage(uint32 _fishermanRewardPercentage) public useDeployer { vm.assume(_fishermanRewardPercentage > disputeManager.MAX_FISHERMAN_REWARD_CUT()); address disputeManagerImplementation = address(new DisputeManager(address(controller))); bytes memory expectedError = abi.encodeWithSelector( @@ -146,7 +148,7 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { ); } - function test_Constructor_RevertIf_InvalidMaxSlashingPercentage(uint32 _maxSlashingPercentage) public useDeployer { + function test_DisputeManager_Constructor_RevertIf_InvalidMaxSlashingPercentage(uint32 _maxSlashingPercentage) public useDeployer { vm.assume(_maxSlashingPercentage > PPMMath.MAX_PPM); address disputeManagerImplementation = address(new DisputeManager(address(controller))); bytes memory expectedError = abi.encodeWithSelector( @@ -163,4 +165,4 @@ contract DisputeManagerConstructorTest is DisputeManagerTest { _maxSlashingPercentage ); } -} \ No newline at end of file +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/accept.t.sol deleted file mode 100644 index 29e3bb6f5..000000000 --- a/packages/subgraph-service/test/disputeManager/disputes/accept.t.sol +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; -import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "../DisputeManager.t.sol"; -import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; - -contract DisputeManagerAcceptDisputeTest is DisputeManagerTest { - using PPMMath for uint256; - - /* - * TESTS - */ - - function testAccept_IndexingDispute( - uint256 tokens, - uint256 tokensSlash, - uint256 delegationAmount - ) public useIndexer useAllocation(tokens) { - delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); - - resetPrank(users.delegator); - _delegate(delegationAmount); - - uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); - uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); - tokensSlash = bound(tokensSlash, 1, tokensSlashCap); - - uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); - - resetPrank(users.arbitrator); - disputeManager.acceptDispute(disputeID, tokensSlash); - - uint256 fishermanReward = Math.min(tokensSlash, tokens).mulPPM(fishermanRewardPercentage); - uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; - assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance); - } - - function testAccept_QueryDispute( - uint256 tokens, - uint256 tokensSlash, - uint256 delegationAmount - ) public useIndexer useAllocation(tokens) { - delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); - - resetPrank(users.delegator); - _delegate(delegationAmount); - - uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); - uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); - tokensSlash = bound(tokensSlash, 1, tokensSlashCap); - - uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID = _createQueryDispute(); - - resetPrank(users.arbitrator); - disputeManager.acceptDispute(disputeID, tokensSlash); - - uint256 fishermanReward = Math.min(tokensSlash, tokens).mulPPM(fishermanRewardPercentage); - uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; - assertEq(token.balanceOf(users.fisherman), fishermanExpectedBalance); - } - - function testAccept_QueryDisputeConflicting( - uint256 tokens, - uint256 tokensSlash, - uint256 delegationAmount - ) public useIndexer useAllocation(tokens) { - delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); - - resetPrank(users.delegator); - _delegate(delegationAmount); - - uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); - uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); - tokensSlash = bound(tokensSlash, 1, tokensSlashCap); - - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - resetPrank(users.fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - - resetPrank(users.arbitrator); - disputeManager.acceptDispute(disputeID1, tokensSlash); - - uint256 fishermanReward = Math.min(tokensSlash, tokens).mulPPM(fishermanRewardPercentage); - uint256 fishermanExpectedBalance = fishermanPreviousBalance + fishermanReward; - assertEq( - token.balanceOf(users.fisherman), - fishermanExpectedBalance, - "Fisherman should receive 50% of slashed tokens." - ); - - (, , , , , IDisputeManager.DisputeStatus status1, , ) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, , ) = disputeManager.disputes(disputeID2); - assertTrue(status1 == IDisputeManager.DisputeStatus.Accepted, "Dispute 1 should be accepted."); - assertTrue(status2 == IDisputeManager.DisputeStatus.Rejected, "Dispute 2 should be rejected."); - } - - function testAccept_IndexingDispute_RevertIf_SlashAmountTooHigh( - uint256 tokens, - uint256 tokensSlash, - uint256 delegationAmount - ) public useIndexer useAllocation(tokens) { - delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); - - resetPrank(users.delegator); - _delegate(delegationAmount); - - uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); - uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); - tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); - - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); - - resetPrank(users.arbitrator); - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerInvalidTokensSlash.selector, - tokensSlash, - tokensSlashCap - ); - vm.expectRevert(expectedError); - disputeManager.acceptDispute(disputeID, tokensSlash); - } - - function testAccept_QueryDispute_RevertIf_SlashAmountTooHigh( - uint256 tokens, - uint256 tokensSlash, - uint256 delegationAmount - ) public useIndexer useAllocation(tokens) { - delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); - - resetPrank(users.delegator); - _delegate(delegationAmount); - - uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); - uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); - tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); - - bytes32 disputeID = _createQueryDispute(); - - resetPrank(users.arbitrator); - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerInvalidTokensSlash.selector, - tokensSlash, - tokensSlashCap - ); - vm.expectRevert(expectedError); - disputeManager.acceptDispute(disputeID, tokensSlash); - } - - function testAccept_ConflictingQueryDispute_RevertIf_SlashAmountTooHigh( - uint256 tokens, - uint256 tokensSlash, - uint256 delegationAmount - ) public useIndexer useAllocation(tokens) { - delegationAmount = bound(delegationAmount, 1 ether, 10_000_000_000 ether); - - resetPrank(users.delegator); - _delegate(delegationAmount); - - uint256 stakeSnapshot = disputeManager.getStakeSnapshot(users.indexer); - uint256 tokensSlashCap = stakeSnapshot.mulPPM(maxSlashingPercentage); - tokensSlash = bound(tokensSlash, tokensSlashCap + 1 wei, type(uint256).max); - - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - resetPrank(users.fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - - resetPrank(users.arbitrator); - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerInvalidTokensSlash.selector, - tokensSlash, - tokensSlashCap - ); - vm.expectRevert(expectedError); - disputeManager.acceptDispute(disputeID1, tokensSlash); - } - - function testAccept_RevertIf_CallerIsNotArbitrator( - uint256 tokens, - uint256 tokensSlash - ) public useIndexer useAllocation(tokens) { - tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); - - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); - - // attempt to accept dispute as fisherman - resetPrank(users.fisherman); - vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); - disputeManager.acceptDispute(disputeID, tokensSlash); - } -} diff --git a/packages/subgraph-service/test/disputeManager/disputes/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/cancel.t.sol deleted file mode 100644 index abd55e051..000000000 --- a/packages/subgraph-service/test/disputeManager/disputes/cancel.t.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "../DisputeManager.t.sol"; - -contract DisputeManagerCancelDisputeTest is DisputeManagerTest { - - /* - * TESTS - */ - - function testCancel_Dispute( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); - - // skip to end of dispute period - skip(disputePeriod + 1); - - resetPrank(users.fisherman); - disputeManager.cancelDispute(disputeID); - - assertEq(token.balanceOf(users.fisherman), fishermanPreviousBalance, "Fisherman should receive their deposit back."); - } - - function testCancel_QueryDisputeConflicting( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - resetPrank(users.fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - - // skip to end of dispute period - skip(disputePeriod + 1); - - disputeManager.cancelDispute(disputeID1); - - (, , , , , IDisputeManager.DisputeStatus status1, ,) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ,) = disputeManager.disputes(disputeID2); - assertTrue(status1 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 1 should be cancelled."); - assertTrue(status2 == IDisputeManager.DisputeStatus.Cancelled, "Dispute 2 should be cancelled."); - } - - function testCancel_RevertIf_CallerIsNotFisherman( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); - - resetPrank(users.arbitrator); - vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotFisherman.selector)); - disputeManager.cancelDispute(disputeID); - } -} diff --git a/packages/subgraph-service/test/disputeManager/disputes/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/create.t.sol deleted file mode 100644 index 05147ec73..000000000 --- a/packages/subgraph-service/test/disputeManager/disputes/create.t.sol +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "../DisputeManager.t.sol"; - -contract DisputeManagerCreateDisputeTest is DisputeManagerTest { - - /* - * TESTS - */ - - function testCreate_IndexingDispute( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); - assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); - } - - function testCreate_QueryDispute( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 disputeID = _createQueryDispute(); - assertTrue(disputeManager.isDisputeCreated(disputeID), "Dispute should be created."); - } - - function testCreate_QueryDisputeConflict( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - resetPrank(users.fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - assertTrue(disputeManager.isDisputeCreated(disputeID1), "Dispute 1 should be created."); - assertTrue(disputeManager.isDisputeCreated(disputeID2), "Dispute 2 should be created."); - } - - function testCreate_RevertWhen_DisputeAlreadyCreated( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); - - // Create another dispute with different fisherman - address otherFisherman = makeAddr("otherFisherman"); - resetPrank(otherFisherman); - mint(otherFisherman, disputeDeposit); - token.approve(address(disputeManager), disputeDeposit); - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerDisputeAlreadyCreated.selector, - disputeID - ); - vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI1")); - vm.stopPrank(); - } - - function testCreate_RevertIf_TokensNotApproved() public useFisherman { - bytes memory expectedError = abi.encodeWithSignature( - "ERC20InsufficientAllowance(address,uint256,uint256)", - address(disputeManager), - 0, - disputeDeposit - ); - vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI3")); - vm.stopPrank(); - } - - function testCreate_RevertIf_AllocationDoesNotExist() public useFisherman { - token.approve(address(disputeManager), disputeDeposit); - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerIndexerNotFound.selector, - allocationID - ); - vm.expectRevert(expectedError); - disputeManager.createIndexingDispute(allocationID, bytes32("POI4")); - vm.stopPrank(); - } - - function testCreate_RevertIf_ConflictingAttestationsResponsesAreTheSame() public useFisherman { - bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); - bytes32 responseCID = keccak256(abi.encodePacked("Response CID")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( - responseCID, - subgraphDeploymentId, - responseCID, - subgraphDeploymentId - ); - - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerNonConflictingAttestations.selector, - requestCID, - responseCID, - subgraphDeploymentId, - requestCID, - responseCID, - subgraphDeploymentId - ); - vm.expectRevert(expectedError); - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); - } - - function testCreate_RevertIf_ConflictingAttestationsHaveDifferentSubgraph() public { - bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId1 = keccak256(abi.encodePacked("Subgraph Deployment ID 1")); - bytes32 subgraphDeploymentId2 = keccak256(abi.encodePacked("Subgraph Deployment ID 2")); - - (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( - responseCID1, - subgraphDeploymentId1, - responseCID2, - subgraphDeploymentId2 - ); - - vm.prank(users.fisherman); - bytes memory expectedError = abi.encodeWithSelector( - IDisputeManager.DisputeManagerNonConflictingAttestations.selector, - requestCID, - responseCID1, - subgraphDeploymentId1, - requestCID, - responseCID2, - subgraphDeploymentId2 - ); - vm.expectRevert(expectedError); - disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); - } -} diff --git a/packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol b/packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol new file mode 100644 index 000000000..cd229dbc4 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; + +contract DisputeManagerDisputeTest is DisputeManagerTest { + using PPMMath for uint256; + + /* + * TESTS + */ + + function test_Dispute_Accept_RevertIf_DisputeDoesNotExist( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + bytes32 disputeID = bytes32("0x0"); + + resetPrank(users.arbitrator); + vm.expectRevert(abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidDispute.selector, + disputeID + )); + disputeManager.acceptDispute(disputeID, tokensSlash); + } + + function test_Dispute_Accept_RevertIf_SlashZeroTokens( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI101")); + + // attempt to accept dispute with 0 tokens slashed + resetPrank(users.arbitrator); + uint256 maxTokensToSlash = uint256(maxSlashingPercentage).mulPPM(tokens); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerInvalidTokensSlash.selector, 0, maxTokensToSlash)); + disputeManager.acceptDispute(disputeID, 0); + } + + function test_Dispute_Reject_RevertIf_DisputeDoesNotExist( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + bytes32 disputeID = bytes32("0x0"); + + resetPrank(users.arbitrator); + vm.expectRevert(abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidDispute.selector, + disputeID + )); + disputeManager.rejectDispute(disputeID); + } + + function test_Dispute_Draw_RevertIf_DisputeDoesNotExist( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + bytes32 disputeID = bytes32("0x0"); + + resetPrank(users.arbitrator); + vm.expectRevert(abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidDispute.selector, + disputeID + )); + disputeManager.drawDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/draw.t.sol deleted file mode 100644 index 75dabaa2f..000000000 --- a/packages/subgraph-service/test/disputeManager/disputes/draw.t.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; -import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; -import { DisputeManagerTest } from "../DisputeManager.t.sol"; - -contract DisputeManagerDrawDisputeTest is DisputeManagerTest { - - /* - * TESTS - */ - - function testDraw_Dispute( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - uint256 fishermanPreviousBalance = token.balanceOf(users.fisherman); - bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI32")); - - resetPrank(users.arbitrator); - disputeManager.drawDispute(disputeID); - - assertEq(token.balanceOf(users.fisherman), fishermanPreviousBalance, "Fisherman should receive their deposit back."); - } - - function testDraw_QueryDisputeConflicting( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); - bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); - bytes32 subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); - - (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( - responseCID1, - subgraphDeploymentId, - responseCID2, - subgraphDeploymentId - ); - - resetPrank(users.fisherman); - (bytes32 disputeID1, bytes32 disputeID2) = disputeManager.createQueryDisputeConflict( - attestationData1, - attestationData2 - ); - - resetPrank(users.arbitrator); - disputeManager.drawDispute(disputeID1); - - (, , , , , IDisputeManager.DisputeStatus status1, ,) = disputeManager.disputes(disputeID1); - (, , , , , IDisputeManager.DisputeStatus status2, ,) = disputeManager.disputes(disputeID2); - assertTrue(status1 == IDisputeManager.DisputeStatus.Drawn, "Dispute 1 should be drawn."); - assertTrue(status2 == IDisputeManager.DisputeStatus.Drawn, "Dispute 2 should be drawn."); - } - - function testDraw_RevertIf_CallerIsNotArbitrator( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - bytes32 disputeID = _createIndexingDispute(allocationID,bytes32("POI1")); - - // attempt to draw dispute as fisherman - resetPrank(users.fisherman); - vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); - disputeManager.drawDispute(disputeID); - } -} diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol new file mode 100644 index 000000000..5e0d36132 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerIndexingAcceptDisputeTest is DisputeManagerTest { + using PPMMath for uint256; + + /* + * TESTS + */ + + function test_Indexing_Accept_Dispute( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + resetPrank(users.fisherman); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); + + resetPrank(users.arbitrator); + _acceptDispute(disputeID, tokensSlash); + } + + function test_Indexing_Accept_RevertIf_CallerIsNotArbitrator( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + resetPrank(users.fisherman); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); + + // attempt to accept dispute as fisherman + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.acceptDispute(disputeID, tokensSlash); + } + + function test_Indexing_Accept_RevertWhen_SlashingOverMaxSlashPercentage( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + tokensSlash = bound(tokensSlash, uint256(maxSlashingPercentage).mulPPM(tokens) + 1, type(uint256).max); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI101")); + + // max slashing percentage is 50% + resetPrank(users.arbitrator); + uint256 maxTokensToSlash = uint256(maxSlashingPercentage).mulPPM(tokens); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidTokensSlash.selector, + tokensSlash, + maxTokensToSlash + ); + vm.expectRevert(expectedError); + disputeManager.acceptDispute(disputeID, tokensSlash); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol new file mode 100644 index 000000000..0a09ad7f4 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerIndexingCancelDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Indexing_Cancel_Dispute(uint256 tokens) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1")); + + _cancelDispute(disputeID); + } + + function test_Indexing_Cancel_RevertIf_CallerIsNotFisherman( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1")); + + resetPrank(users.arbitrator); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotFisherman.selector)); + disputeManager.cancelDispute(disputeID); + } + + function test_Indexing_Cancel_RevertIf_DisputePeriodNotOver( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1")); + + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerDisputePeriodNotFinished.selector)); + disputeManager.cancelDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol new file mode 100644 index 000000000..0174315a2 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerIndexingCreateDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Indexing_Create_Dispute( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + _createIndexingDispute(allocationID, bytes32("POI1")); + } + + function test_Indexing_Create_MultipleDisputes() public { + uint256 tokens = 10000 ether; + uint8 numIndexers = 10; + uint256[] memory allocationIDPrivateKeys = new uint256[](numIndexers); + for (uint i = 0; i < numIndexers; i++) { + string memory indexerName = string(abi.encodePacked("Indexer ", i)); + address indexer = createUser(indexerName); + vm.assume(indexer != address(0)); + + resetPrank(indexer); + mint(indexer, tokens); + _createProvision(indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(indexer, abi.encode("url", "geoHash", address(0))); + uint256 allocationIDPrivateKey = uint256(keccak256(abi.encodePacked(i))); + bytes memory data = _createSubgraphAllocationData(indexer, subgraphDeployment, allocationIDPrivateKey, tokens); + _startService(indexer, data); + allocationIDPrivateKeys[i] = allocationIDPrivateKey; + } + + resetPrank(users.fisherman); + for (uint i = 0; i < allocationIDPrivateKeys.length; i++) { + _createIndexingDispute(vm.addr(allocationIDPrivateKeys[i]), bytes32("POI1")); + } + } + + function test_Indexing_Create_RevertWhen_DisputeAlreadyCreated( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1")); + + // Create another dispute with different fisherman + address otherFisherman = makeAddr("otherFisherman"); + resetPrank(otherFisherman); + mint(otherFisherman, disputeDeposit); + token.approve(address(disputeManager), disputeDeposit); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerDisputeAlreadyCreated.selector, + disputeID + ); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1")); + vm.stopPrank(); + } + + function test_Indexing_Create_RevertIf_DepositUnderMinimum(uint256 tokensDeposit) public useFisherman { + tokensDeposit = bound(tokensDeposit, 0, disputeDeposit - 1); + token.approve(address(disputeManager), tokensDeposit); + bytes memory expectedError = abi.encodeWithSignature( + "ERC20InsufficientAllowance(address,uint256,uint256)", + address(disputeManager), + tokensDeposit, + disputeDeposit + ); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, bytes32("POI3")); + vm.stopPrank(); + } + + function test_Indexing_Create_RevertIf_AllocationDoesNotExist( + uint256 tokens + ) public useFisherman { + tokens = bound(tokens, disputeDeposit, 10_000_000_000 ether); + token.approve(address(disputeManager), tokens); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerIndexerNotFound.selector, + allocationID + ); + vm.expectRevert(expectedError); + disputeManager.createIndexingDispute(allocationID, bytes32("POI4")); + vm.stopPrank(); + } + + function test_Indexing_Create_RevertIf_IndexerIsBelowStake( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Close allocation + bytes memory data = abi.encode(allocationID); + _stopService(users.indexer, data); + // Thaw, deprovision and unstake + address subgraphDataServiceAddress = address(subgraphService); + _thawDeprovisionAndUnstake(users.indexer, subgraphDataServiceAddress, tokens); + + // Attempt to create dispute + resetPrank(users.fisherman); + token.approve(address(disputeManager), tokens); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerZeroTokens.selector)); + disputeManager.createIndexingDispute(allocationID, bytes32("POI1")); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol new file mode 100644 index 000000000..3df590f74 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerIndexingDrawDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Indexing_Draw_Dispute(uint256 tokens) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI32")); + + resetPrank(users.arbitrator); + _drawDispute(disputeID); + } + + function test_Indexing_Draw_RevertIf_CallerIsNotArbitrator( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID = _createIndexingDispute(allocationID,bytes32("POI1")); + + // attempt to draw dispute as fisherman + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.drawDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol new file mode 100644 index 000000000..5401c0afe --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerIndexingRejectDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Indexing_Reject_Dispute(uint256 tokens) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID = _createIndexingDispute(allocationID, bytes32("POI1")); + + resetPrank(users.arbitrator); + _rejectDispute(disputeID); + } + + function test_Indexing_Reject_RevertIf_CallerIsNotArbitrator( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + bytes32 disputeID =_createIndexingDispute(allocationID, bytes32("POI1")); + + // attempt to accept dispute as fisherman + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.rejectDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol new file mode 100644 index 000000000..d0f00234d --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { Attestation } from "../../../../contracts/libraries/Attestation.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryAcceptDisputeTest is DisputeManagerTest { + using PPMMath for uint256; + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID = keccak256(abi.encodePacked("Response CID")); + bytes32 private subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + /* + * TESTS + */ + + function test_Query_Accept_Dispute( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + resetPrank(users.arbitrator); + _acceptDispute(disputeID, tokensSlash); + } + + function test_Query_Accept_RevertIf_CallerIsNotArbitrator( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + // attempt to accept dispute as fisherman + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.acceptDispute(disputeID, tokensSlash); + } + + function test_Query_Accept_RevertWhen_SlashingOverMaxSlashPercentage( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, uint256(maxSlashingPercentage).mulPPM(tokens) + 1, type(uint256).max); + + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + // max slashing percentage is 50% + resetPrank(users.arbitrator); + uint256 maxTokensToSlash = uint256(maxSlashingPercentage).mulPPM(tokens); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidTokensSlash.selector, + tokensSlash, + maxTokensToSlash + ); + vm.expectRevert(expectedError); + disputeManager.acceptDispute(disputeID, tokensSlash); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol new file mode 100644 index 000000000..a61db6ad9 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { Attestation } from "../../../../contracts/libraries/Attestation.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryCancelDisputeTest is DisputeManagerTest { + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID = keccak256(abi.encodePacked("Response CID")); + bytes32 private subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + /* + * TESTS + */ + + function test_Query_Cancel_Dispute(uint256 tokens) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + _cancelDispute(disputeID); + } + + function test_Query_Cancel_RevertIf_CallerIsNotFisherman( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + resetPrank(users.arbitrator); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotFisherman.selector)); + disputeManager.cancelDispute(disputeID); + } + + function test_Query_Cancel_RevertIf_DisputePeriodNotOver( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerDisputePeriodNotFinished.selector)); + disputeManager.cancelDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol new file mode 100644 index 000000000..01f27cf66 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { Attestation } from "../../../../contracts/libraries/Attestation.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryCreateDisputeTest is DisputeManagerTest { + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID = keccak256(abi.encodePacked("Response CID")); + bytes32 private subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + /* + * TESTS + */ + + function test_Query_Create_Dispute(uint256 tokens) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + _createQueryDispute(attestationData); + } + + function test_Query_Create_MultipleDisputes_DifferentFisherman( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + _createQueryDispute(attestationData); + + // Create another dispute with different fisherman + address otherFisherman = makeAddr("otherFisherman"); + resetPrank(otherFisherman); + mint(otherFisherman, MAX_TOKENS); + Attestation.Receipt memory otherFishermanReceipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory otherFishermanAttestationData = _createAtestationData(otherFishermanReceipt, allocationIDPrivateKey); + _createQueryDispute(otherFishermanAttestationData); + } + + function test_Query_Create_MultipleDisputes_DifferentIndexer( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Create first dispute for indexer + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + _createQueryDispute(attestationData); + + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + uint256 newAllocationIDKey = uint256(keccak256(abi.encodePacked("newAllocationID"))); + mint(newIndexer, tokens); + resetPrank(newIndexer); + _createProvision(newIndexer, tokens, maxSlashingPercentage, disputePeriod); + _register(newIndexer, abi.encode("url", "geoHash", 0x0)); + bytes memory data = _createSubgraphAllocationData(newIndexer, subgraphDeployment, newAllocationIDKey, tokens); + _startService(newIndexer, data); + + // Create another dispute with same receipt but different indexer + resetPrank(users.fisherman); + bytes memory attestationData2 = _createAtestationData(receipt, newAllocationIDKey); + _createQueryDispute(attestationData2); + } + + function test_Query_Create_RevertIf_Duplicate(uint256 tokens) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + Attestation.Receipt memory newReceipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory newAttestationData = _createAtestationData(newReceipt, allocationIDPrivateKey); + token.approve(address(disputeManager), disputeDeposit); + vm.expectRevert(abi.encodeWithSelector( + IDisputeManager.DisputeManagerDisputeAlreadyCreated.selector, + disputeID + )); + disputeManager.createQueryDispute(newAttestationData); + } + + function test_Query_Create_RevertIf_DepositUnderMinimum(uint256 tokensDispute) public useFisherman { + tokensDispute = bound(tokensDispute, 0, disputeDeposit - 1); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + + token.approve(address(disputeManager), tokensDispute); + bytes memory expectedError = abi.encodeWithSignature( + "ERC20InsufficientAllowance(address,uint256,uint256)", + address(disputeManager), + tokensDispute, + disputeDeposit + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDispute(attestationData); + } + + function test_Query_Create_RevertIf_AllocationDoesNotExist( + uint256 tokens + ) public useFisherman { + tokens = bound(tokens, disputeDeposit, 10_000_000_000 ether); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + token.approve(address(disputeManager), tokens); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerIndexerNotFound.selector, + allocationID + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDispute(attestationData); + vm.stopPrank(); + } + + function test_Query_Create_RevertIf_IndexerIsBelowStake( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Close allocation + bytes memory data = abi.encode(allocationID); + _stopService(users.indexer, data); + + // Thaw, deprovision and unstake + address subgraphDataServiceAddress = address(subgraphService); + _thawDeprovisionAndUnstake(users.indexer, subgraphDataServiceAddress, tokens); + + // Atempt to create dispute + resetPrank(users.fisherman); + token.approve(address(disputeManager), tokens); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerZeroTokens.selector)); + disputeManager.createQueryDispute(attestationData); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol new file mode 100644 index 000000000..1b9c96ad2 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { Attestation } from "../../../../contracts/libraries/Attestation.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryDrawDisputeTest is DisputeManagerTest { + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID = keccak256(abi.encodePacked("Response CID")); + bytes32 private subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + /* + * TESTS + */ + + function test_Query_Draw_Dispute( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + resetPrank(users.arbitrator); + _drawDispute(disputeID); + } + + function test_Query_Draw_RevertIf_CallerIsNotArbitrator( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + // attempt to draw dispute as fisherman + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.drawDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol new file mode 100644 index 000000000..07c738a90 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { Attestation } from "../../../../contracts/libraries/Attestation.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryRejectDisputeTest is DisputeManagerTest { + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID = keccak256(abi.encodePacked("Response CID")); + bytes32 private subgraphDeploymentId = keccak256(abi.encodePacked("Subgraph Deployment ID")); + + /* + * TESTS + */ + + function test_Query_Reject_Dispute( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + resetPrank(users.arbitrator); + _rejectDispute(disputeID); + } + + function test_Query_Reject_RevertIf_CallerIsNotArbitrator( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + Attestation.Receipt memory receipt = _createAttestationReceipt(requestCID, responseCID, subgraphDeploymentId); + bytes memory attestationData = _createAtestationData(receipt, allocationIDPrivateKey); + bytes32 disputeID = _createQueryDispute(attestationData); + + // attempt to accept dispute as fisherman + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.rejectDispute(disputeID); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol new file mode 100644 index 000000000..1cfde0a8c --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryConflictAcceptDisputeTest is DisputeManagerTest { + using PPMMath for uint256; + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 private responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + + /* + * TESTS + */ + + function test_Query_Conflict_Accept_Dispute( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + resetPrank(users.arbitrator); + _acceptDispute(disputeID1, tokensSlash); + } + + function test_Query_Conflict_Accept_RevertIf_CallerIsNotArbitrator( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, 1, uint256(maxSlashingPercentage).mulPPM(tokens)); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + // attempt to accept dispute as fisherman + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.acceptDispute(disputeID1, tokensSlash); + } + + function test_Query_Conflict_Accept_RevertWhen_SlashingOverMaxSlashPercentage( + uint256 tokens, + uint256 tokensSlash + ) public useIndexer useAllocation(tokens) { + tokensSlash = bound(tokensSlash, uint256(maxSlashingPercentage).mulPPM(tokens) + 1, type(uint256).max); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + // max slashing percentage is 50% + resetPrank(users.arbitrator); + uint256 maxTokensToSlash = uint256(maxSlashingPercentage).mulPPM(tokens); + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerInvalidTokensSlash.selector, + tokensSlash, + maxTokensToSlash + ); + vm.expectRevert(expectedError); + disputeManager.acceptDispute(disputeID1, tokensSlash); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol new file mode 100644 index 000000000..4de2b3155 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryConflictCancelDisputeTest is DisputeManagerTest { + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 private responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + + /* + * TESTS + */ + + function test_Query_Conflict_Cancel_Dispute( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + _cancelDispute(disputeID1); + } + + function test_Query_Conflict_Cancel_RevertIf_CallerIsNotFisherman( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + resetPrank(users.indexer); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotFisherman.selector)); + disputeManager.cancelDispute(disputeID1); + } + + function test_Query_Conflict_Cancel_RevertIf_DisputePeriodNotOver( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerDisputePeriodNotFinished.selector)); + disputeManager.cancelDispute(disputeID1); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol new file mode 100644 index 000000000..2f54983ae --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { Attestation } from "../../../../contracts/libraries/Attestation.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryConflictCreateDisputeTest is DisputeManagerTest { + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 private responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + + /* + * TESTS + */ + + function test_Query_Conflict_Create_DisputeAttestation( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + resetPrank(users.fisherman); + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + _createQueryDisputeConflict(attestationData1, attestationData2); + } + + function test_Query_Conflict_Create_DisputeAttestationDifferentIndexers( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + uint256 newAllocationIDKey = uint256(keccak256(abi.encodePacked("newAllocationID"))); + mint(newIndexer, tokens); + resetPrank(newIndexer); + _createProvision(newIndexer, tokens, maxSlashingPercentage, disputePeriod); + _register(newIndexer, abi.encode("url", "geoHash", 0x0)); + bytes memory data = _createSubgraphAllocationData(newIndexer, subgraphDeployment, newAllocationIDKey, tokens); + _startService(newIndexer, data); + + // Create query conflict dispute + resetPrank(users.fisherman); + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + newAllocationIDKey + ); + + _createQueryDisputeConflict(attestationData1, attestationData2); + } + + function test_Query_Conflict_Create_RevertIf_AttestationsResponsesAreTheSame() public useFisherman { + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID1, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerNonConflictingAttestations.selector, + requestCID, + responseCID1, + subgraphDeployment, + requestCID, + responseCID1, + subgraphDeployment + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + } + + function test_Query_Conflict_Create_RevertIf_AttestationsHaveDifferentSubgraph() public useFisherman { + bytes32 subgraphDeploymentId2 = keccak256(abi.encodePacked("Subgraph Deployment ID 2")); + + Attestation.Receipt memory receipt1 = _createAttestationReceipt(requestCID, responseCID1, subgraphDeployment); + bytes memory attestationData1 = _createAtestationData(receipt1, allocationIDPrivateKey); + + Attestation.Receipt memory receipt2 = _createAttestationReceipt(requestCID, responseCID2, subgraphDeploymentId2); + bytes memory attestationData2 = _createAtestationData(receipt2, allocationIDPrivateKey); + + bytes memory expectedError = abi.encodeWithSelector( + IDisputeManager.DisputeManagerNonConflictingAttestations.selector, + requestCID, + responseCID1, + subgraphDeployment, + requestCID, + responseCID2, + subgraphDeploymentId2 + ); + vm.expectRevert(expectedError); + disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol new file mode 100644 index 000000000..5127b56a5 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryConflictDrawDisputeTest is DisputeManagerTest { + + bytes32 private requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 private responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 private responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + + /* + * TESTS + */ + + function test_Query_Conflict_Draw_Dispute( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + resetPrank(users.arbitrator); + _drawDispute(disputeID1); + } + + function test_Query_Conflict_Draw_RevertIf_CallerIsNotArbitrator( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1,) = _createQueryDisputeConflict(attestationData1, attestationData2); + + // attempt to draw dispute as fisherman + resetPrank(users.fisherman); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerNotArbitrator.selector)); + disputeManager.drawDispute(disputeID1); + } +} diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol new file mode 100644 index 000000000..078969267 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../../DisputeManager.t.sol"; + +contract DisputeManagerQueryConflictRejectDisputeTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Query_Conflict_Reject_Revert( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + bytes32 requestCID = keccak256(abi.encodePacked("Request CID")); + bytes32 responseCID1 = keccak256(abi.encodePacked("Response CID 1")); + bytes32 responseCID2 = keccak256(abi.encodePacked("Response CID 2")); + + (bytes memory attestationData1, bytes memory attestationData2) = _createConflictingAttestations( + requestCID, + subgraphDeployment, + responseCID1, + responseCID2, + allocationIDPrivateKey, + allocationIDPrivateKey + ); + + resetPrank(users.fisherman); + (bytes32 disputeID1, bytes32 disputeID2) = _createQueryDisputeConflict(attestationData1, attestationData2); + + resetPrank(users.arbitrator); + vm.expectRevert(abi.encodeWithSelector( + IDisputeManager.DisputeManagerMustAcceptRelatedDispute.selector, + disputeID1, + disputeID2 + )); + disputeManager.rejectDispute(disputeID1); + } +} diff --git a/packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol b/packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol new file mode 100644 index 000000000..53e36a497 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +contract DisputeManagerGovernanceArbitratorTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Governance_SetArbitrator() public useGovernor { + address arbitrator = makeAddr("newArbitrator"); + _setArbitrator(arbitrator); + } + + function test_Governance_RevertWhen_ZeroAddress() public useGovernor { + address arbitrator = address(0); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerInvalidZeroAddress.selector)); + disputeManager.setArbitrator(arbitrator); + } + + function test_Governance_RevertWhen_NotGovernor() public useFisherman { + address arbitrator = makeAddr("newArbitrator"); + vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, users.fisherman)); + disputeManager.setArbitrator(arbitrator); + } +} diff --git a/packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol b/packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol new file mode 100644 index 000000000..163157886 --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +contract DisputeManagerGovernanceDisputeDepositTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Governance_SetDisputeDeposit(uint256 disputeDeposit) public useGovernor { + vm.assume(disputeDeposit > 0); + _setDisputeDeposit(disputeDeposit); + } + + function test_Governance_RevertWhen_ZeroValue() public useGovernor { + uint256 disputeDeposit = 0; + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerInvalidDisputeDeposit.selector, disputeDeposit)); + disputeManager.setDisputeDeposit(disputeDeposit); + } + + function test_Governance_RevertWhen_NotGovernor() public useFisherman { + uint256 disputeDeposit = 100 ether; + vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, users.fisherman)); + disputeManager.setDisputeDeposit(disputeDeposit); + } +} diff --git a/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol b/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol index 0c821e2a2..5a09bdd03 100644 --- a/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol +++ b/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol @@ -13,10 +13,9 @@ contract DisputeManagerGovernanceFishermanRewardCutTest is DisputeManagerTest { * TESTS */ - function test_Governance_SetFishermanRewardCut() public useGovernor { - uint32 fishermanRewardCut = 1000; - disputeManager.setFishermanRewardCut(fishermanRewardCut); - assertEq(disputeManager.fishermanRewardCut(), fishermanRewardCut, "Fisherman reward cut should be set."); + function test_Governance_SetFishermanRewardCut(uint32 fishermanRewardCut) public useGovernor { + vm.assume(fishermanRewardCut <= disputeManager.MAX_FISHERMAN_REWARD_CUT()); + _setFishermanRewardCut(fishermanRewardCut); } function test_Governance_RevertWhen_OverMaximumValue(uint32 fishermanRewardCut) public useGovernor { diff --git a/packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol b/packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol new file mode 100644 index 000000000..343e514bc --- /dev/null +++ b/packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDisputeManager } from "../../../contracts/interfaces/IDisputeManager.sol"; +import { DisputeManagerTest } from "../DisputeManager.t.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +contract DisputeManagerGovernanceMaxSlashingCutTest is DisputeManagerTest { + + /* + * TESTS + */ + + function test_Governance_SetMaxSlashingCut(uint32 maxSlashingCut) public useGovernor { + vm.assume(maxSlashingCut <= MAX_PPM); + _setMaxSlashingCut(maxSlashingCut); + } + + function test_Governance_RevertWhen_NotPPM(uint32 maxSlashingCut) public useGovernor { + vm.assume(maxSlashingCut > MAX_PPM); + vm.expectRevert(abi.encodeWithSelector(IDisputeManager.DisputeManagerInvalidMaxSlashingCut.selector, maxSlashingCut)); + disputeManager.setMaxSlashingCut(maxSlashingCut); + } + + function test_Governance_RevertWhen_NotGovernor() public useFisherman { + uint32 maxSlashingCut = 1000; + vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, users.fisherman)); + disputeManager.setMaxSlashingCut(maxSlashingCut); + } +} diff --git a/packages/subgraph-service/test/shared/HorizonStakingShared.t.sol b/packages/subgraph-service/test/shared/HorizonStakingShared.t.sol new file mode 100644 index 000000000..28a22e1a2 --- /dev/null +++ b/packages/subgraph-service/test/shared/HorizonStakingShared.t.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol"; + +import { SubgraphBaseTest } from "../SubgraphBaseTest.t.sol"; + +abstract contract HorizonStakingSharedTest is SubgraphBaseTest { + + /* + * HELPERS + */ + + function _createProvision( + address _indexer, + uint256 _tokens, + uint32 _maxSlashingPercentage, + uint64 _disputePeriod + ) internal { + _stakeTo(_indexer, _tokens); + staking.provision(_indexer, address(subgraphService), _tokens, _maxSlashingPercentage, _disputePeriod); + } + + function _addToProvision(address _indexer, uint256 _tokens) internal { + _stakeTo(_indexer, _tokens); + staking.addToProvision(_indexer, address(subgraphService), _tokens); + } + + function _delegate(address _indexer, address _verifier, uint256 _tokens, uint256 _minSharesOut) internal { + staking.delegate(_indexer, _verifier, _tokens, _minSharesOut); + } + + function _setDelegationFeeCut( + address _indexer, + address _verifier, + IGraphPayments.PaymentTypes _paymentType, + uint256 _cut + ) internal { + staking.setDelegationFeeCut(_indexer, _verifier, _paymentType, _cut); + } + + function _thawDeprovisionAndUnstake(address _indexer, address _verifier, uint256 _tokens) internal { + // Initiate thaw request + staking.thaw(_indexer, _verifier, _tokens); + + // Skip thawing period + IHorizonStakingTypes.Provision memory provision = staking.getProvision(_indexer, _verifier); + skip(provision.thawingPeriod + 1); + + // Deprovision and unstake + staking.deprovision(_indexer, _verifier, 0); + staking.unstake(_tokens); + } + + function _setProvisionParameters( + address _indexer, + address _verifier, + uint32 _maxVerifierCut, + uint64 _thawingPeriod + ) internal { + staking.setProvisionParameters(_indexer, _verifier, _maxVerifierCut, _thawingPeriod); + } + + /* + * PRIVATE + */ + + function _stakeTo(address _indexer, uint256 _tokens) private { + token.approve(address(staking), _tokens); + staking.stakeTo(_indexer, _tokens); + } +} diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index 8c0b9d0fe..1067acf14 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -3,9 +3,14 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { SubgraphBaseTest } from "../SubgraphBaseTest.t.sol"; +import { Allocation } from "../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../contracts/utilities/AllocationManager.sol"; +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { ISubgraphService } from "../../contracts/interfaces/ISubgraphService.sol"; -abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { +import { HorizonStakingSharedTest } from "./HorizonStakingShared.t.sol"; + +abstract contract SubgraphServiceSharedTest is HorizonStakingSharedTest { /* * VARIABLES @@ -28,9 +33,22 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { modifier useAllocation(uint256 tokens) { vm.assume(tokens > minimumProvisionTokens); vm.assume(tokens < 10_000_000_000 ether); - _createProvision(tokens); - _registerIndexer(address(0)); - _startService(tokens); + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + bytes memory data = _createSubgraphAllocationData(users.indexer, subgraphDeployment, allocationIDPrivateKey, tokens); + _startService(users.indexer, data); + _; + } + + modifier useDelegation(uint256 tokens) { + // 1e18 is the minimum delegation amount until L2 transfers are removed + vm.assume(tokens > 1e18); + vm.assume(tokens < 10_000_000_000 ether); + (, address msgSender,) = vm.readCallers(); + resetPrank(users.delegator); + token.approve(address(staking), tokens); + _delegate(users.indexer, address(subgraphService), tokens, 0); + resetPrank(msgSender); _; } @@ -45,29 +63,109 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { } /* - * HELPERS + * ACTIONS */ - function _createProvision(uint256 tokens) internal { - _stakeTo(users.indexer, tokens); - staking.provision(users.indexer, address(subgraphService), tokens, maxSlashingPercentage, disputePeriod); + function _register(address _indexer, bytes memory _data) internal { + (string memory url, string memory geohash, address rewardsDestination) = abi.decode( + _data, + (string, string, address) + ); + + vm.expectEmit(address(subgraphService)); + emit IDataService.ServiceProviderRegistered( + _indexer, + _data + ); + + // Register indexer + subgraphService.register(_indexer, _data); + + // Check registered indexer data + ISubgraphService.Indexer memory indexer = _getIndexer(_indexer); + assertEq(indexer.registeredAt, block.timestamp); + assertEq(indexer.url, url); + assertEq(indexer.geoHash, geohash); + + // Check rewards destination + assertEq(subgraphService.rewardsDestination(_indexer), rewardsDestination); } - function _addToProvision(address _indexer, uint256 _tokens) internal { - _stakeTo(_indexer, _tokens); - staking.addToProvision(_indexer, address(subgraphService), _tokens); + function _startService(address _indexer, bytes memory _data) internal { + (bytes32 subgraphDeploymentId, uint256 tokens, address allocationId,) = abi.decode( + _data, + (bytes32, uint256, address, bytes) + ); + uint256 previousSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeploymentId); + + vm.expectEmit(address(subgraphService)); + emit IDataService.ServiceStarted(_indexer, _data); + + // TODO: improve this + uint256 accRewardsPerAllocatedToken = 0; + if (rewardsManager.subgraphs(subgraphDeploymentId)) { + accRewardsPerAllocatedToken = rewardsManager.rewardsPerSubgraphAllocationUpdate(); + } + + // Start service + subgraphService.startService(_indexer, _data); + + // Check allocation data + Allocation.State memory allocation = subgraphService.getAllocation(allocationId); + assertEq(allocation.tokens, tokens); + assertEq(allocation.indexer, _indexer); + assertEq(allocation.subgraphDeploymentId, subgraphDeploymentId); + assertEq(allocation.createdAt, block.timestamp); + assertEq(allocation.closedAt, 0); + assertEq(allocation.lastPOIPresentedAt, 0); + assertEq(allocation.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken); + assertEq(allocation.accRewardsPending, 0); + + // Check subgraph deployment allocated tokens + uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeploymentId); + assertEq(subgraphAllocatedTokens, previousSubgraphAllocatedTokens + tokens); } - function _registerIndexer(address rewardsDestination) internal { - subgraphService.register(users.indexer, abi.encode("url", "geoHash", rewardsDestination)); + function _stopService(address _indexer, bytes memory _data) internal { + address allocationId = abi.decode(_data, (address)); + assertTrue(subgraphService.isActiveAllocation(allocationId)); + + Allocation.State memory allocation = subgraphService.getAllocation(allocationId); + uint256 previousSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(allocation.subgraphDeploymentId); + + vm.expectEmit(address(subgraphService)); + emit AllocationManager.AllocationClosed(_indexer, allocationId, allocation.subgraphDeploymentId, allocation.tokens); + emit IDataService.ServiceStopped(_indexer, _data); + + // stop allocation + subgraphService.stopService(_indexer, _data); + + // update allocation + allocation = subgraphService.getAllocation(allocationId); + + // check allocation + assertEq(allocation.closedAt, block.timestamp); + + // check subgraph deployment allocated tokens + uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); + assertEq(subgraphAllocatedTokens, previousSubgraphAllocatedTokens - allocation.tokens); } - function _startService(uint256 tokens) internal { - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + /* + * HELPERS + */ - bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); - subgraphService.startService(users.indexer, data); + function _createSubgraphAllocationData( + address _indexer, + bytes32 _subgraphDeployment, + uint256 _allocationIdPrivateKey, + uint256 _tokens + ) internal view returns (bytes memory) { + address allocationId = vm.addr(_allocationIdPrivateKey); + bytes32 digest = subgraphService.encodeAllocationProof(_indexer, allocationId); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_allocationIdPrivateKey, digest); + + return abi.encode(_subgraphDeployment, _tokens, allocationId, abi.encodePacked(r, s, v)); } function _delegate(uint256 tokens) internal { @@ -76,11 +174,15 @@ abstract contract SubgraphServiceSharedTest is SubgraphBaseTest { } /* - * PRIVATE + * PRIVATE FUNCTIONS */ - function _stakeTo(address _indexer, uint256 _tokens) internal { - token.approve(address(staking), _tokens); - staking.stakeTo(_indexer, _tokens); + function _getIndexer(address _indexer) private view returns (ISubgraphService.Indexer memory) { + (uint256 registeredAt, string memory url, string memory geoHash) = subgraphService.indexers(_indexer); + return ISubgraphService.Indexer({ + registeredAt: registeredAt, + url: url, + geoHash: geoHash + }); } } diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 89b613344..12d20581f 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -6,11 +6,21 @@ import "forge-std/Test.sol"; import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol"; +import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { LinkedList } from "@graphprotocol/horizon/contracts/libraries/LinkedList.sol"; +import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataServiceFees.sol"; +import { Allocation } from "../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../contracts/utilities/AllocationManager.sol"; +import { ISubgraphService } from "../../contracts/interfaces/ISubgraphService.sol"; import { SubgraphServiceSharedTest } from "../shared/SubgraphServiceShared.t.sol"; contract SubgraphServiceTest is SubgraphServiceSharedTest { using PPMMath for uint256; + using Allocation for Allocation.State; + using LinkedList for LinkedList.List; /* * VARIABLES @@ -21,11 +31,18 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { */ modifier useOperator { - vm.startPrank(users.operator); + resetPrank(users.indexer); + staking.setOperator(users.operator, address(subgraphService), true); + resetPrank(users.operator); _; vm.stopPrank(); } + modifier useRewardsDestination { + _setRewardsDestination(users.rewardsDestination); + _; + } + /* * SET UP */ @@ -34,6 +51,285 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { super.setUp(); } + /* + * ACTIONS + */ + + function _setRewardsDestination(address _rewardsDestination) internal { + (, address indexer, ) = vm.readCallers(); + + vm.expectEmit(address(subgraphService)); + emit AllocationManager.RewardsDestinationSet(indexer, _rewardsDestination); + + // Set rewards destination + subgraphService.setRewardsDestination(_rewardsDestination); + + // Check rewards destination + assertEq(subgraphService.rewardsDestination(indexer), _rewardsDestination); + } + + function _acceptProvision(address _indexer, bytes memory _data) internal { + IHorizonStakingTypes.Provision memory provision = staking.getProvision(_indexer, address(subgraphService)); + uint32 maxVerifierCut = provision.maxVerifierCut; + uint64 thawingPeriod = provision.thawingPeriod; + uint32 maxVerifierCutPending = provision.maxVerifierCutPending; + uint64 thawingPeriodPending = provision.thawingPeriodPending; + + vm.expectEmit(address(subgraphService)); + emit IDataService.ProvisionAccepted(_indexer); + + // Accept provision + subgraphService.acceptProvision(_indexer, _data); + + // Update provision after acceptance + provision = staking.getProvision(_indexer, address(subgraphService)); + + // Check that max verifier cut updated to pending value if needed + if (maxVerifierCut != maxVerifierCutPending) { + assertEq(provision.maxVerifierCut, maxVerifierCutPending); + } + + // Check that thawing period updated to pending value if needed + if (thawingPeriod != thawingPeriodPending) { + assertEq(provision.thawingPeriod, thawingPeriodPending); + } + } + + function _resizeAllocation(address _indexer, address _allocationId, uint256 _tokens) internal { + // before state + Allocation.State memory beforeAllocation = subgraphService.getAllocation(_allocationId); + bytes32 subgraphDeploymentId = beforeAllocation.subgraphDeploymentId; + uint256 beforeSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeploymentId); + uint256 beforeAllocatedTokens = subgraphService.allocationProvisionTracker(_indexer); + + uint256 allocatedTokensDelta; + if (_tokens > beforeAllocation.tokens) { + allocatedTokensDelta = _tokens - beforeAllocation.tokens; + } else { + allocatedTokensDelta = beforeAllocation.tokens - _tokens; + } + + vm.expectEmit(address(subgraphService)); + emit AllocationManager.AllocationResized(_indexer, _allocationId, subgraphDeploymentId, _tokens, beforeSubgraphAllocatedTokens); + + // resize allocation + subgraphService.resizeAllocation(_indexer, _allocationId, _tokens); + + // after state + uint256 afterSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeploymentId); + uint256 afterAllocatedTokens = subgraphService.allocationProvisionTracker(_indexer); + Allocation.State memory afterAllocation = subgraphService.getAllocation(_allocationId); + uint256 accRewardsPerAllocatedTokenDelta = afterAllocation.accRewardsPerAllocatedToken - beforeAllocation.accRewardsPerAllocatedToken; + uint256 afterAccRewardsPending = rewardsManager.calcRewards(beforeAllocation.tokens, accRewardsPerAllocatedTokenDelta); + + // check state + if (_tokens > beforeAllocation.tokens) { + assertEq(afterAllocatedTokens, beforeAllocatedTokens + allocatedTokensDelta); + } else { + assertEq(afterAllocatedTokens, beforeAllocatedTokens - allocatedTokensDelta); + } + assertEq(afterAllocation.tokens, _tokens); + assertEq(afterAllocation.accRewardsPerAllocatedToken, rewardsPerSubgraphAllocationUpdate); + assertEq(afterAllocation.accRewardsPending, afterAccRewardsPending); + assertEq(afterSubgraphAllocatedTokens, _tokens); + } + + function _closeStaleAllocation(address _allocationId) internal { + assertTrue(subgraphService.isActiveAllocation(_allocationId)); + + Allocation.State memory allocation = subgraphService.getAllocation(_allocationId); + uint256 previousSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(allocation.subgraphDeploymentId); + + vm.expectEmit(address(subgraphService)); + emit AllocationManager.AllocationClosed(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, allocation.tokens); + + // close stale allocation + subgraphService.closeStaleAllocation(_allocationId); + + // update allocation + allocation = subgraphService.getAllocation(_allocationId); + + // check allocation + assertEq(allocation.closedAt, block.timestamp); + + // check subgraph deployment allocated tokens + uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); + assertEq(subgraphAllocatedTokens, previousSubgraphAllocatedTokens - allocation.tokens); + } + + struct IndexingRewardsData { + bytes32 poi; + uint256 tokensIndexerRewards; + uint256 tokensDelegationRewards; + } + + struct QueryFeeData { + uint256 curationCut; + uint256 protocolPaymentCut; + } + + struct CollectPaymentData { + uint256 rewardsDestinationBalance; + uint256 indexerProvisionBalance; + uint256 delegationPoolBalance; + uint256 indexerBalance; + uint256 curationBalance; + uint256 lockedTokens; + } + + function _collect(address _indexer, IGraphPayments.PaymentTypes _paymentType, bytes memory _data) internal { + address allocationId; + uint256 paymentCollected = 0; + Allocation.State memory allocation; + CollectPaymentData memory collectPaymentDataBefore; + + // PaymentType.IndexingRewards variables + IndexingRewardsData memory indexingRewardsData; + uint32 delegationRatio = subgraphService.delegationRatio(); + address rewardsDestination = subgraphService.rewardsDestination(_indexer); + collectPaymentDataBefore.rewardsDestinationBalance = token.balanceOf(rewardsDestination); + collectPaymentDataBefore.indexerProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); + collectPaymentDataBefore.delegationPoolBalance = staking.getDelegatedTokensAvailable(_indexer, address(subgraphService)); + + // PaymentType.QueryFee variables + QueryFeeData memory queryFeeData; + queryFeeData.protocolPaymentCut = graphPayments.PROTOCOL_PAYMENT_CUT(); + collectPaymentDataBefore.indexerBalance = token.balanceOf(_indexer); + collectPaymentDataBefore.curationBalance = token.balanceOf(address(curation)); + collectPaymentDataBefore.lockedTokens = subgraphService.feesProvisionTracker(_indexer); + + if (_paymentType == IGraphPayments.PaymentTypes.QueryFee) { + // Recover RAV data + ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); + allocationId = abi.decode(signedRav.rav.metadata, (address)); + allocation = subgraphService.getAllocation(allocationId); + address payer = _recoverRAVSigner(signedRav); + + // Total amount of tokens collected for indexer + uint256 tokensCollected = tapCollector.tokensCollected(address(subgraphService), _indexer, payer); + // Find out how much of the payment was collected via this RAV + paymentCollected = signedRav.rav.valueAggregate - tokensCollected; + + // Calculate curation cut + uint256 curationFeesCut = subgraphService.curationFeesCut(); + queryFeeData.curationCut = curation.isCurated(allocation.subgraphDeploymentId) ? curationFeesCut : 0; + uint256 tokensCurators = paymentCollected.mulPPM(queryFeeData.curationCut); + + vm.expectEmit(address(subgraphService)); + emit ISubgraphService.QueryFeesCollected(_indexer, paymentCollected, tokensCurators); + } else if (_paymentType == IGraphPayments.PaymentTypes.IndexingRewards) { + // Recover IndexingRewards data + (allocationId, indexingRewardsData.poi) = abi.decode(_data, (address, bytes32)); + allocation = subgraphService.getAllocation(allocationId); + + // Calculate accumulated tokens, this depends on the rewards manager which we have mocked + uint256 accRewardsPerTokens = allocation.tokens.mulPPM(rewardsManager.rewardsPerSignal()); + // Calculate the payment collected by the indexer for this transaction + paymentCollected = accRewardsPerTokens - allocation.accRewardsPerAllocatedToken; + + uint256 delegatorCut = staking.getDelegationFeeCut( + allocation.indexer, + address(subgraphService), + // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead + IGraphPayments.PaymentTypes.IndexingFee + ); + indexingRewardsData.tokensDelegationRewards = paymentCollected.mulPPM(delegatorCut); + indexingRewardsData.tokensIndexerRewards = paymentCollected - indexingRewardsData.tokensDelegationRewards; + + vm.expectEmit(address(subgraphService)); + emit AllocationManager.IndexingRewardsCollected( + allocation.indexer, + allocationId, + allocation.subgraphDeploymentId, + paymentCollected, + indexingRewardsData.tokensIndexerRewards, + indexingRewardsData.tokensDelegationRewards, + indexingRewardsData.poi + ); + } + + vm.expectEmit(address(subgraphService)); + emit IDataService.ServicePaymentCollected(_indexer, _paymentType, paymentCollected); + + // collect rewards + subgraphService.collect(_indexer, _paymentType, _data); + + // Collect payment data after + CollectPaymentData memory collectPaymentDataAfter; + collectPaymentDataAfter.rewardsDestinationBalance = token.balanceOf(rewardsDestination); + collectPaymentDataAfter.indexerProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); + collectPaymentDataAfter.delegationPoolBalance = staking.getDelegatedTokensAvailable(_indexer, address(subgraphService)); + collectPaymentDataAfter.indexerBalance = token.balanceOf(_indexer); + collectPaymentDataAfter.curationBalance = token.balanceOf(address(curation)); + collectPaymentDataAfter.lockedTokens = subgraphService.feesProvisionTracker(_indexer); + + if (_paymentType == IGraphPayments.PaymentTypes.QueryFee) { + // Check indexer got paid the correct amount + uint256 tokensProtocol = paymentCollected.mulPPM(protocolPaymentCut); + uint256 curationTokens = paymentCollected.mulPPM(queryFeeData.curationCut); + uint256 expectedIndexerTokensPayment = paymentCollected - tokensProtocol - curationTokens; + assertEq(collectPaymentDataAfter.indexerBalance, collectPaymentDataBefore.indexerBalance + expectedIndexerTokensPayment); + + // Check curation got paid the correct amount + assertEq(collectPaymentDataAfter.curationBalance, collectPaymentDataBefore.curationBalance + curationTokens); + + // Check locked tokens + uint256 stakeToFeesRatio = subgraphService.stakeToFeesRatio(); + uint256 tokensToLock = paymentCollected * stakeToFeesRatio; + assertEq(collectPaymentDataAfter.lockedTokens, collectPaymentDataBefore.lockedTokens + tokensToLock); + + // Check the stake claim + LinkedList.List memory claimsList = _getClaimList(_indexer); + bytes32 claimId = _buildStakeClaimId(_indexer, claimsList.nonce - 1); + IDataServiceFees.StakeClaim memory stakeClaim = _getStakeClaim(claimId); + uint64 disputePeriod = disputeManager.getDisputePeriod(); + assertEq(stakeClaim.tokens, tokensToLock); + assertEq(stakeClaim.createdAt, block.timestamp); + assertEq(stakeClaim.releaseAt, block.timestamp + disputePeriod); + assertEq(stakeClaim.nextClaim, bytes32(0)); + } else { + // Update allocation after collecting rewards + allocation = subgraphService.getAllocation(allocationId); + + // Check allocation state + assertEq(allocation.accRewardsPending, 0); + uint256 accRewardsPerAllocatedToken = rewardsManager.onSubgraphAllocationUpdate(allocation.subgraphDeploymentId); + assertEq(allocation.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken); + assertEq(allocation.lastPOIPresentedAt, block.timestamp); + + // Check indexer got paid the correct amount + if (rewardsDestination == address(0)) { + // If rewards destination is address zero indexer should get paid to their provision balance + assertEq( + collectPaymentDataAfter.indexerProvisionBalance, + collectPaymentDataBefore.indexerProvisionBalance + indexingRewardsData.tokensIndexerRewards + ); + } else { + // If rewards destination is set indexer should get paid to the rewards destination address + assertEq( + collectPaymentDataAfter.rewardsDestinationBalance, + collectPaymentDataBefore.rewardsDestinationBalance + indexingRewardsData.tokensIndexerRewards + ); + } + + // Check delegation pool got paid the correct amount + assertEq( + collectPaymentDataAfter.delegationPoolBalance, + collectPaymentDataBefore.delegationPoolBalance + indexingRewardsData.tokensDelegationRewards + ); + + // If after collecting indexing rewards the indexer is over allocated the allcation should close + uint256 tokensAvailable = staking.getTokensAvailable(_indexer, address(subgraphService), delegationRatio); + if (allocation.tokens <= tokensAvailable) { + // Indexer isn't over allocated so allocation should still be open + assertTrue(allocation.isOpen()); + } else { + // Indexer is over allocated so allocation should be closed + assertFalse(allocation.isOpen()); + } + } + } + /* * HELPERS */ @@ -45,37 +341,36 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { token.approve(address(staking), _tokens); staking.stakeTo(_indexer, _tokens); staking.provision(_indexer, address(subgraphService), _tokens, maxSlashingPercentage, disputePeriod); - subgraphService.register(_indexer, abi.encode("url", "geoHash", address(0))); + _register(_indexer, abi.encode("url", "geoHash", address(0))); (address newIndexerAllocationId, uint256 newIndexerAllocationKey) = makeAddrAndKey("newIndexerAllocationId"); bytes32 digest = subgraphService.encodeAllocationProof(_indexer, newIndexerAllocationId); (uint8 v, bytes32 r, bytes32 s) = vm.sign(newIndexerAllocationKey, digest); bytes memory data = abi.encode(subgraphDeployment, _tokens, newIndexerAllocationId, abi.encodePacked(r, s, v)); - subgraphService.startService(_indexer, data); + _startService(_indexer, data); } - function _stopAllocation(address _indexer, address _allocationID) internal { - resetPrank(_indexer); - assertTrue(subgraphService.isActiveAllocation(_allocationID)); - bytes memory data = abi.encode(_allocationID); - vm.expectEmit(address(subgraphService)); - emit IDataService.ServiceStopped(_indexer, data); - subgraphService.stopService(_indexer, data); + /* + * PRIVATE FUNCTIONS + */ - uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); - assertEq(subgraphAllocatedTokens, 0); + function _recoverRAVSigner(ITAPCollector.SignedRAV memory _signedRAV) private view returns (address) { + bytes32 messageHash = tapCollector.encodeRAV(_signedRAV.rav); + return ECDSA.recover(messageHash, _signedRAV.signature); } - function _collectIndexingRewards(address _indexer, address _allocationID, uint256 _tokens) internal { - resetPrank(_indexer); - IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; - bytes memory data = abi.encode(_allocationID, bytes32("POI1")); + function _getClaimList(address _indexer) private view returns (LinkedList.List memory) { + (bytes32 head, bytes32 tail, uint256 nonce, uint256 count) = subgraphService.claimsLists(_indexer); + return LinkedList.List(head, tail, nonce, count); + } - uint256 indexerPreviousProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); - subgraphService.collect(_indexer, paymentType, data); + function _buildStakeClaimId(address _indexer, uint256 _nonce) private view returns (bytes32) { + return keccak256(abi.encodePacked(address(subgraphService), _indexer, _nonce)); + } - uint256 indexerProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); - assertEq(indexerProvisionBalance, indexerPreviousProvisionBalance + _tokens.mulPPM(rewardsPerSignal)); + function _getStakeClaim(bytes32 _claimId) private view returns (IDataServiceFees.StakeClaim memory) { + (uint256 tokens, uint256 createdAt, uint256 releaseAt, bytes32 nextClaim) = subgraphService.claims(_claimId); + return IDataServiceFees.StakeClaim(tokens, createdAt, releaseAt, nextClaim); } } diff --git a/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol b/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol deleted file mode 100644 index a2d8ef4a7..000000000 --- a/packages/subgraph-service/test/subgraphService/allocate/resize.t.sol +++ /dev/null @@ -1,129 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { Allocation } from "../../../contracts/libraries/Allocation.sol"; -import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; -import { SubgraphServiceTest } from "../SubgraphService.t.sol"; -import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; - -contract SubgraphServiceAllocateResizeTest is SubgraphServiceTest { - - /* - * Helpers - */ - - function _setupResize(address _indexer, uint256 _tokens) private { - token.approve(address(staking), _tokens); - staking.stakeTo(_indexer, _tokens); - staking.addToProvision(_indexer, address(subgraphService), _tokens); - } - - function _resizeAllocation(address _indexer, address _allocationID, bytes32 _subgraphDeployment, uint256 _tokens) private { - // before - uint256 beforeSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); - uint256 beforeAllocatedTokens = subgraphService.allocationProvisionTracker(_indexer); - Allocation.State memory beforeAllocation = subgraphService.getAllocation(_allocationID); - - uint256 allocatedTokensDelta; - if (_tokens > beforeAllocation.tokens) { - allocatedTokensDelta = _tokens - beforeAllocation.tokens; - } else { - allocatedTokensDelta = beforeAllocation.tokens - _tokens; - } - - // resize - vm.expectEmit(address(subgraphService)); - emit AllocationManager.AllocationResized(_indexer, _allocationID, _subgraphDeployment, _tokens, beforeSubgraphAllocatedTokens); - subgraphService.resizeAllocation(_indexer, _allocationID, _tokens); - - // after - uint256 afterSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(_subgraphDeployment); - uint256 afterAllocatedTokens = subgraphService.allocationProvisionTracker(_indexer); - Allocation.State memory afterAllocation = subgraphService.getAllocation(_allocationID); - uint256 accRewardsPerAllocatedTokenDelta = afterAllocation.accRewardsPerAllocatedToken - beforeAllocation.accRewardsPerAllocatedToken; - uint256 afterAccRewardsPending = rewardsManager.calcRewards(beforeAllocation.tokens, accRewardsPerAllocatedTokenDelta); - - //assert - if (_tokens > beforeAllocation.tokens) { - assertEq(afterAllocatedTokens, beforeAllocatedTokens + allocatedTokensDelta); - } else { - assertEq(afterAllocatedTokens, beforeAllocatedTokens - allocatedTokensDelta); - } - assertEq(afterAllocation.tokens, _tokens); - assertEq(afterAllocation.accRewardsPerAllocatedToken, rewardsPerSubgraphAllocationUpdate); - assertEq(afterAllocation.accRewardsPending, afterAccRewardsPending); - assertEq(afterSubgraphAllocatedTokens, _tokens); - } - - /* - * TESTS - */ - - function testResize_Allocation(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { - resizeTokens = bound(resizeTokens, 1, MAX_TOKENS); - vm.assume(resizeTokens != tokens); - - mint(users.indexer, resizeTokens); - _addToProvision(users.indexer, resizeTokens); - _resizeAllocation(users.indexer, allocationID, subgraphDeployment, resizeTokens); - } - - function testResize_Allocation_AfterCollectingIndexingRewards(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { - resizeTokens = bound(resizeTokens, 1, MAX_TOKENS); - vm.assume(resizeTokens != tokens); - - mint(users.indexer, resizeTokens); - _collectIndexingRewards(users.indexer, allocationID, tokens); - _addToProvision(users.indexer, resizeTokens); - _resizeAllocation(users.indexer, allocationID, subgraphDeployment, resizeTokens); - } - - function testResize_Allocation_SecondTime(uint256 tokens, uint256 firstResizeTokens, uint256 secondResizeTokens) public useIndexer useAllocation(tokens) { - firstResizeTokens = bound(firstResizeTokens, 1, MAX_TOKENS); - secondResizeTokens = bound(secondResizeTokens, 1, MAX_TOKENS); - vm.assume(firstResizeTokens != tokens); - vm.assume(secondResizeTokens != firstResizeTokens); - - mint(users.indexer, firstResizeTokens); - _addToProvision(users.indexer, firstResizeTokens); - _resizeAllocation(users.indexer, allocationID, subgraphDeployment, firstResizeTokens); - - mint(users.indexer, secondResizeTokens); - _addToProvision(users.indexer, secondResizeTokens); - _resizeAllocation(users.indexer, allocationID, subgraphDeployment, secondResizeTokens); - } - - function testResize_RevertWhen_NotAuthorized(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { - resizeTokens = bound(resizeTokens, tokens + 1, MAX_TOKENS); - - address newIndexer = makeAddr("newIndexer"); - _createAndStartAllocation(newIndexer, tokens); - vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, - newIndexer, - allocationID - )); - subgraphService.resizeAllocation(newIndexer, allocationID, resizeTokens); - } - - function testResize_RevertWhen_SameSize(uint256 tokens) public useIndexer useAllocation(tokens) { - vm.expectRevert(abi.encodeWithSelector( - AllocationManager.AllocationManagerAllocationSameSize.selector, - allocationID, - tokens - )); - subgraphService.resizeAllocation(users.indexer, allocationID, tokens); - } - - function testResize_RevertIf_AllocationIsClosed(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { - resizeTokens = bound(resizeTokens, tokens + 1, MAX_TOKENS); - _stopAllocation(users.indexer, allocationID); - vm.expectRevert(abi.encodeWithSelector( - AllocationManager.AllocationManagerAllocationClosed.selector, - allocationID - )); - subgraphService.resizeAllocation(users.indexer, allocationID, resizeTokens); - } -} diff --git a/packages/subgraph-service/test/subgraphService/allocate/start.t.sol b/packages/subgraph-service/test/subgraphService/allocate/start.t.sol deleted file mode 100644 index 65e4ec35b..000000000 --- a/packages/subgraph-service/test/subgraphService/allocate/start.t.sol +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; -import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; -import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; - -import { Allocation } from "../../../contracts/libraries/Allocation.sol"; -import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; -import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; -import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol"; -import { SubgraphServiceTest } from "../SubgraphService.t.sol"; - -contract SubgraphServiceAllocateStartTest is SubgraphServiceTest { - - /* - * Helpers - */ - - function _generateData(uint256 tokens) private view returns(bytes memory) { - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - return abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); - } - - /* - * TESTS - */ - - function testStart_Allocation(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - - _createProvision(tokens); - _registerIndexer(address(0)); - - bytes memory data = _generateData(tokens); - vm.expectEmit(address(subgraphService)); - emit IDataService.ServiceStarted(users.indexer, data); - subgraphService.startService(users.indexer, data); - - Allocation.State memory allocation = subgraphService.getAllocation(allocationID); - assertEq(allocation.tokens, tokens); - assertEq(allocation.indexer, users.indexer); - assertEq(allocation.subgraphDeploymentId, subgraphDeployment); - assertEq(allocation.createdAt, block.timestamp); - assertEq(allocation.closedAt, 0); - assertEq(allocation.lastPOIPresentedAt, 0); - assertEq(allocation.accRewardsPerAllocatedToken, 0); - assertEq(allocation.accRewardsPending, 0); - - uint256 subgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeployment); - assertEq(subgraphAllocatedTokens, tokens); - } - - function testStart_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - - _createProvision(tokens); - _registerIndexer(address(0)); - - resetPrank(users.operator); - bytes memory data = _generateData(tokens); - vm.expectRevert(abi.encodeWithSelector( - ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer - )); - subgraphService.startService(users.indexer, data); - } - - function testStart_RevertWhen_NoValidProvision(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - - bytes memory data = _generateData(tokens); - vm.expectRevert(abi.encodeWithSelector( - ProvisionManager.ProvisionManagerProvisionNotFound.selector, - users.indexer - )); - subgraphService.startService(users.indexer, data); - } - - function testStart_RevertWhen_NotRegistered(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - - _createProvision(tokens); - - bytes memory data = _generateData(tokens); - vm.expectRevert(abi.encodeWithSelector( - ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, - users.indexer - )); - subgraphService.startService(users.indexer, data); - } - - function testStart_RevertWhen_ZeroAllocationId(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - - _createProvision(tokens); - _registerIndexer(address(0)); - - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, address(0)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); - bytes memory data = abi.encode(subgraphDeployment, tokens, address(0), abi.encodePacked(r, s, v)); - vm.expectRevert(abi.encodeWithSelector( - AllocationManager.AllocationManagerInvalidZeroAllocationId.selector - )); - subgraphService.startService(users.indexer, data); - } - - function testStart_RevertWhen_InvalidSignature(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - - _createProvision(tokens); - _registerIndexer(address(0)); - - (address signer, uint256 signerPrivateKey) = makeAddrAndKey("invalidSigner"); - bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, digest); - bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); - vm.expectRevert(abi.encodeWithSelector( - AllocationManager.AllocationManagerInvalidAllocationProof.selector, - signer, - allocationID - )); - subgraphService.startService(users.indexer, data); - } - - function testStart_RevertWhen_ArealdyExists(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - - _createProvision(tokens); - _registerIndexer(address(0)); - - bytes32 slot = keccak256(abi.encode(allocationID, uint256(158))); - vm.store(address(subgraphService), slot, bytes32(uint256(uint160(users.indexer)))); - vm.store(address(subgraphService), bytes32(uint256(slot) + 1), subgraphDeployment); - - bytes memory data = _generateData(tokens); - vm.expectRevert(abi.encodeWithSelector( - LegacyAllocation.LegacyAllocationExists.selector, - allocationID - )); - subgraphService.startService(users.indexer, data); - } - - function testStart_RevertWhen_NotEnoughTokens( - uint256 tokens, - uint256 lockTokens - ) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS - 1); - lockTokens = bound(lockTokens, tokens + 1, MAX_TOKENS); - - _createProvision(tokens); - _registerIndexer(address(0)); - - bytes memory data = _generateData(lockTokens); - vm.expectRevert(abi.encodeWithSelector( - ProvisionTracker.ProvisionTrackerInsufficientTokens.selector, - tokens, - lockTokens - )); - subgraphService.startService(users.indexer, data); - } -} diff --git a/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol b/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol new file mode 100644 index 000000000..3e6672dd7 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; + +import { Allocation } from "../../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceAllocationCloseStaleTest is SubgraphServiceTest { + + address private permissionlessBob = makeAddr("permissionlessBob"); + + /* + * TESTS + */ + + function test_SubgraphService_Allocation_CloseStale( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Skip forward + skip(maxPOIStaleness + 1); + + resetPrank(permissionlessBob); + _closeStaleAllocation(allocationID); + } + + function test_SubgraphService_Allocation_CloseStale_AfterCollecting( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Simulate POIs being submitted + uint8 numberOfPOIs = 5; + uint256 timeBetweenPOIs = 5 days; + + for (uint8 i = 0; i < numberOfPOIs; i++) { + // Skip forward + skip(timeBetweenPOIs); + + bytes memory data = abi.encode(allocationID, bytes32("POI1")); + _collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data); + } + + // Skip forward so that the allocation is stale + skip(maxPOIStaleness + 1); + + // Close the stale allocation + resetPrank(permissionlessBob); + _closeStaleAllocation(allocationID); + } + + function test_SubgraphService_Allocation_CloseStale_RevertIf_NotStale( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Simulate POIs being submitted + uint8 numberOfPOIs = 20; + uint256 timeBetweenPOIs = (maxPOIStaleness - 1) / numberOfPOIs; + + for (uint8 i = 0; i < numberOfPOIs; i++) { + // Skip forward + skip(timeBetweenPOIs); + + resetPrank(users.indexer); + + bytes memory data = abi.encode(allocationID, bytes32("POI1")); + _collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data); + + resetPrank(permissionlessBob); + vm.expectRevert( + abi.encodeWithSelector( + ISubgraphService.SubgraphServiceAllocationNotStale.selector, + allocationID, + block.timestamp + ) + ); + subgraphService.closeStaleAllocation(allocationID); + } + } + + function test_SubgraphService_Allocation_CloseStale_RevertIf_Altruistic( + uint256 tokens + ) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = _createSubgraphAllocationData(users.indexer, subgraphDeployment, allocationIDPrivateKey, 0); + _startService(users.indexer, data); + + skip(maxPOIStaleness + 1); + + resetPrank(permissionlessBob); + vm.expectRevert( + abi.encodeWithSelector( + ISubgraphService.SubgraphServiceAllocationIsAltruistic.selector, + allocationID + ) + ); + subgraphService.closeStaleAllocation(allocationID); + } +} diff --git a/packages/subgraph-service/test/subgraphService/allocation/resize.t.sol b/packages/subgraph-service/test/subgraphService/allocation/resize.t.sol new file mode 100644 index 000000000..3da7c5a0c --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/allocation/resize.t.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { Allocation } from "../../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; + +contract SubgraphServiceAllocationResizeTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function test_SubgraphService_Allocation_Resize(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, 1, MAX_TOKENS); + vm.assume(resizeTokens != tokens); + + mint(users.indexer, resizeTokens); + _addToProvision(users.indexer, resizeTokens); + _resizeAllocation(users.indexer, allocationID, resizeTokens); + } + + function test_SubgraphService_Allocation_Resize_AfterCollectingIndexingRewards(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, 1, MAX_TOKENS); + vm.assume(resizeTokens != tokens); + + mint(users.indexer, resizeTokens); + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory data = abi.encode(allocationID, bytes32("POI1")); + _collect(users.indexer, paymentType, data); + _addToProvision(users.indexer, resizeTokens); + _resizeAllocation(users.indexer, allocationID, resizeTokens); + } + + function test_SubgraphService_Allocation_Resize_SecondTime(uint256 tokens, uint256 firstResizeTokens, uint256 secondResizeTokens) public useIndexer useAllocation(tokens) { + firstResizeTokens = bound(firstResizeTokens, 1, MAX_TOKENS); + secondResizeTokens = bound(secondResizeTokens, 1, MAX_TOKENS); + vm.assume(firstResizeTokens != tokens); + vm.assume(secondResizeTokens != firstResizeTokens); + + mint(users.indexer, firstResizeTokens); + _addToProvision(users.indexer, firstResizeTokens); + _resizeAllocation(users.indexer, allocationID, firstResizeTokens); + + mint(users.indexer, secondResizeTokens); + _addToProvision(users.indexer, secondResizeTokens); + _resizeAllocation(users.indexer, allocationID, secondResizeTokens); + } + + function test_SubgraphService_Allocation_Resize_RevertWhen_NotAuthorized(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, tokens + 1, MAX_TOKENS); + + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, + newIndexer, + allocationID + )); + subgraphService.resizeAllocation(newIndexer, allocationID, resizeTokens); + } + + function test_SubgraphService_Allocation_Resize_RevertWhen_SameSize(uint256 tokens) public useIndexer useAllocation(tokens) { + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerAllocationSameSize.selector, + allocationID, + tokens + )); + subgraphService.resizeAllocation(users.indexer, allocationID, tokens); + } + + function test_SubgraphService_Allocation_Resize_RevertIf_AllocationIsClosed(uint256 tokens, uint256 resizeTokens) public useIndexer useAllocation(tokens) { + resizeTokens = bound(resizeTokens, tokens + 1, MAX_TOKENS); + bytes memory data = abi.encode(allocationID); + _stopService(users.indexer, data); + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerAllocationClosed.selector, + allocationID + )); + subgraphService.resizeAllocation(users.indexer, allocationID, resizeTokens); + } +} diff --git a/packages/subgraph-service/test/subgraphService/allocation/start.t.sol b/packages/subgraph-service/test/subgraphService/allocation/start.t.sol new file mode 100644 index 000000000..6db5e73db --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/allocation/start.t.sol @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol"; + +import { Allocation } from "../../../contracts/libraries/Allocation.sol"; +import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceAllocationStartTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function test_SubgraphService_Allocation_Start(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = _generateData(tokens); + _startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_AllowsZeroTokens(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = _generateData(0); + _startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_ByOperator(uint256 tokens) public useOperator { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = _generateData(tokens); + _startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + resetPrank(users.operator); + bytes memory data = _generateData(tokens); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_NoValidProvision(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + bytes memory data = _generateData(tokens); + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerProvisionNotFound.selector, + users.indexer + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_NotRegistered(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + + bytes memory data = _generateData(tokens); + vm.expectRevert(abi.encodeWithSelector( + ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, + users.indexer + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_ZeroAllocationId(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, address(0)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(allocationIDPrivateKey, digest); + bytes memory data = abi.encode(subgraphDeployment, tokens, address(0), abi.encodePacked(r, s, v)); + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerInvalidZeroAllocationId.selector + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_InvalidSignature(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + (address signer, uint256 signerPrivateKey) = makeAddrAndKey("invalidSigner"); + bytes32 digest = subgraphService.encodeAllocationProof(users.indexer, allocationID); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, digest); + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, abi.encodePacked(r, s, v)); + vm.expectRevert(abi.encodeWithSelector( + AllocationManager.AllocationManagerInvalidAllocationProof.selector, + signer, + allocationID + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_InvalidData(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = abi.encode(subgraphDeployment, tokens, allocationID, _generateRandomHexBytes(32)); + vm.expectRevert(abi.encodeWithSelector( + ECDSA.ECDSAInvalidSignatureLength.selector, + 32 + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_ArealdyExists(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes32 slot = keccak256(abi.encode(allocationID, uint256(158))); + vm.store(address(subgraphService), slot, bytes32(uint256(uint160(users.indexer)))); + vm.store(address(subgraphService), bytes32(uint256(slot) + 1), subgraphDeployment); + + bytes memory data = _generateData(tokens); + vm.expectRevert(abi.encodeWithSelector( + LegacyAllocation.LegacyAllocationExists.selector, + allocationID + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_ReusingAllocationId(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = _generateData(tokens); + _startService(users.indexer, data); + + vm.expectRevert(abi.encodeWithSelector( + Allocation.AllocationAlreadyExists.selector, + allocationID + )); + subgraphService.startService(users.indexer, data); + } + + function test_SubgraphService_Allocation_Start_RevertWhen_NotEnoughTokens( + uint256 tokens, + uint256 lockTokens + ) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS - 1); + lockTokens = bound(lockTokens, tokens + 1, MAX_TOKENS); + + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + bytes memory data = _generateData(lockTokens); + vm.expectRevert(abi.encodeWithSelector( + ProvisionTracker.ProvisionTrackerInsufficientTokens.selector, + tokens, + lockTokens + )); + subgraphService.startService(users.indexer, data); + } + + /* + * PRIVATE FUNCTIONS + */ + + function _generateData(uint256 tokens) private view returns(bytes memory) { + return _createSubgraphAllocationData(users.indexer, subgraphDeployment, allocationIDPrivateKey, tokens); + } + + function _generateRandomHexBytes(uint256 length) private view returns (bytes memory) { + bytes memory randomBytes = new bytes(length); + for (uint256 i = 0; i < length; i++) { + randomBytes[i] = bytes1(uint8(uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, i))) % 256)); + } + return randomBytes; + } +} diff --git a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol similarity index 70% rename from packages/subgraph-service/test/subgraphService/allocate/stop.t.sol rename to packages/subgraph-service/test/subgraphService/allocation/stop.t.sol index fff5c457f..84b9da27e 100644 --- a/packages/subgraph-service/test/subgraphService/allocate/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol @@ -13,20 +13,18 @@ import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; -contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { - /* - * Helpers - */ +contract SubgraphServiceAllocationStopTest is SubgraphServiceTest { /* * TESTS */ - function testStop_Allocation(uint256 tokens) public useIndexer useAllocation(tokens) { - _stopAllocation(users.indexer, allocationID); + function test_SubgraphService_Allocation_Stop(uint256 tokens) public useIndexer useAllocation(tokens) { + bytes memory data = abi.encode(allocationID); + _stopService(users.indexer, data); } - function testStop_RevertWhen_IndexerIsNotTheAllocationOwner( + function test_SubgraphService_Allocation_Stop_RevertWhen_IndexerIsNotTheAllocationOwner( uint256 tokens ) public useIndexer useAllocation(tokens) { // Setup new indexer @@ -45,7 +43,7 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { subgraphService.stopService(newIndexer, data); } - function testStop_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { + function test_SubgraphService_Allocation_Stop_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { resetPrank(users.operator); bytes memory data = abi.encode(allocationID); vm.expectRevert( @@ -58,7 +56,7 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { subgraphService.stopService(users.indexer, data); } - function testStop_RevertWhen_NotRegistered() public useIndexer { + function test_SubgraphService_Allocation_Stop_RevertWhen_NotRegistered() public useIndexer { bytes memory data = abi.encode(allocationID); vm.expectRevert( abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, users.indexer) @@ -66,21 +64,10 @@ contract SubgraphServiceAllocateStopTest is SubgraphServiceTest { subgraphService.stopService(users.indexer, data); } - function testStop_RevertWhen_NotOpen(uint256 tokens) public useIndexer useAllocation(tokens) { + function test_SubgraphService_Allocation_Stop_RevertWhen_NotOpen(uint256 tokens) public useIndexer useAllocation(tokens) { bytes memory data = abi.encode(allocationID); - subgraphService.stopService(users.indexer, data); + _stopService(users.indexer, data); vm.expectRevert(abi.encodeWithSelector(Allocation.AllocationClosed.selector, allocationID, block.timestamp)); subgraphService.stopService(users.indexer, data); } - - function testCloseStaleAllocation( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - address permissionlessBob = makeAddr("permissionlessBob"); - - skip(maxPOIStaleness + 1); - - resetPrank(permissionlessBob); - subgraphService.closeStaleAllocation(allocationID); - } } diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index a04b248a3..4891a4a75 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -3,228 +3,22 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; -import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; -import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; -import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; -import { Allocation } from "../../../contracts/libraries/Allocation.sol"; -import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol"; import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; -contract SubgraphServiceRegisterTest is SubgraphServiceTest { - using PPMMath for uint128; - using PPMMath for uint256; - using Allocation for Allocation.State; - - address signer; - uint256 signerPrivateKey; - - /* - * HELPERS - */ - - function _getQueryFeeEncodedData(address indexer, uint128 tokens) private view returns (bytes memory) { - ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(indexer, tokens); - bytes32 messageHash = tapCollector.encodeRAV(rav); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, messageHash); - bytes memory signature = abi.encodePacked(r, s, v); - ITAPCollector.SignedRAV memory signedRAV = ITAPCollector.SignedRAV(rav, signature); - return abi.encode(signedRAV); - } - - function _getRAV( - address indexer, - uint128 tokens - ) private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { - return - ITAPCollector.ReceiptAggregateVoucher({ - dataService: address(subgraphService), - serviceProvider: indexer, - timestampNs: 0, - valueAggregate: tokens, - metadata: abi.encode(allocationID) - }); - } - - function _approveCollector(uint256 tokens) private { - address msgSender; - (, msgSender, ) = vm.readCallers(); - resetPrank(signer); - mint(signer, tokens); - escrow.approveCollector(address(tapCollector), tokens); - token.approve(address(escrow), tokens); - escrow.deposit(users.indexer, tokens); - resetPrank(msgSender); - } - - /* - * SET UP - */ - - function setUp() public virtual override { - super.setUp(); - (signer, signerPrivateKey) = makeAddrAndKey("signer"); - vm.label({ account: signer, newLabel: "signer" }); - } +contract SubgraphServiceCollectTest is SubgraphServiceTest { /* * TESTS */ - function testCollect_QueryFees( - uint256 tokensAllocated, - uint256 tokensPayment - ) public useIndexer useAllocation(tokensAllocated) { - vm.assume(tokensAllocated > minimumProvisionTokens * stakeToFeesRatio); - uint256 maxTokensPayment = tokensAllocated / stakeToFeesRatio > type(uint128).max - ? type(uint128).max - : tokensAllocated / stakeToFeesRatio; - tokensPayment = bound(tokensPayment, minimumProvisionTokens, maxTokensPayment); - - _approveCollector(tokensPayment); - - uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - - bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokensPayment)); - uint256 tokensCollected = subgraphService.collect(users.indexer, IGraphPayments.PaymentTypes.QueryFee, data); - - uint256 indexerBalance = token.balanceOf(users.indexer); - uint256 tokensProtocol = tokensCollected.mulPPM(protocolPaymentCut); - uint256 curationTokens = tokensCollected.mulPPM(curationCut); - - uint256 expectedIndexerTokensPayment = tokensCollected - tokensProtocol - curationTokens; - assertEq(indexerBalance, indexerPreviousBalance + expectedIndexerTokensPayment); - } - - function testCollect_MultipleQueryFees( - uint256 tokensAllocated, - uint256 numPayments - ) public useIndexer useAllocation(tokensAllocated) { - vm.assume(tokensAllocated > minimumProvisionTokens * stakeToFeesRatio); - numPayments = bound(numPayments, 1, 10); - uint256 tokensPayment = tokensAllocated / stakeToFeesRatio / numPayments; - - _approveCollector(tokensAllocated); - - uint256 accTokensPayment = 0; - for (uint i = 0; i < numPayments; i++) { - accTokensPayment = accTokensPayment + tokensPayment; - uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - - bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(accTokensPayment)); - uint256 tokensCollected = subgraphService.collect( - users.indexer, - IGraphPayments.PaymentTypes.QueryFee, - data - ); - - uint256 indexerBalance = token.balanceOf(users.indexer); - uint256 tokensProtocol = tokensCollected.mulPPM(protocolPaymentCut); - uint256 curationTokens = tokensCollected.mulPPM(curationCut); - - uint256 expectedIndexerTokensPayment = tokensCollected - tokensProtocol - curationTokens; - assertEq(indexerBalance, indexerPreviousBalance + expectedIndexerTokensPayment); - } - } - - function testCollect_IndexingRewards(uint256 tokens) public useIndexer useAllocation(tokens) { - _collectIndexingRewards(users.indexer, allocationID, tokens); - - Allocation.State memory afterAllocation = subgraphService.getAllocation(allocationID); - assertEq(afterAllocation.isOpen(), true); - } - - function testCollect_IndexingRewards_When_OverAllocated(uint256 tokens) public useIndexer { - tokens = bound(tokens, minimumProvisionTokens * 2, 10_000_000_000 ether); - - // setup allocation - _createProvision(tokens); - _registerIndexer(address(0)); - _startService(tokens); - - // thaw some tokens to become over allocated - staking.thaw(users.indexer, address(subgraphService), tokens / 2); - - // this collection should close the allocation - _collectIndexingRewards(users.indexer, allocationID, tokens); - - Allocation.State memory afterAllocation = subgraphService.getAllocation(allocationID); - assertEq(afterAllocation.isOpen(), false); - } - - function testCollect_RevertWhen_InvalidPayment(uint256 tokens) public useIndexer useAllocation(tokens) { + function test_SubgraphService_Collect_RevertWhen_InvalidPayment(uint256 tokens) public useIndexer useAllocation(tokens) { IGraphPayments.PaymentTypes invalidPaymentType = IGraphPayments.PaymentTypes.IndexingFee; vm.expectRevert( abi.encodeWithSelector(ISubgraphService.SubgraphServiceInvalidPaymentType.selector, invalidPaymentType) ); subgraphService.collect(users.indexer, invalidPaymentType, ""); } - - function testCollect_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { - IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; - bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); - resetPrank(users.operator); - vm.expectRevert( - abi.encodeWithSelector( - ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer - ) - ); - subgraphService.collect(users.indexer, paymentType, data); - } - - function testCollect_QueryFees_RevertWhen_IndexerIsNotAllocationOwner( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; - // Setup new indexer - address newIndexer = makeAddr("newIndexer"); - _createAndStartAllocation(newIndexer, tokens); - - // This data is for user.indexer allocationId - bytes memory data = _getQueryFeeEncodedData(newIndexer, uint128(tokens)); - - resetPrank(newIndexer); - vm.expectRevert( - abi.encodeWithSelector( - ISubgraphService.SubgraphServiceInvalidRAV.selector, - newIndexer, - users.indexer - ) - ); - subgraphService.collect(newIndexer, paymentType, data); - } - - function testCollect_QueryFees_RevertWhen_CollectingOtherIndexersFees( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; - // Setup new indexer - address newIndexer = makeAddr("newIndexer"); - _createAndStartAllocation(newIndexer, tokens); - bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); - vm.expectRevert( - abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerMismatch.selector, users.indexer, newIndexer) - ); - subgraphService.collect(newIndexer, paymentType, data); - } - - function testCollect_IndexingFees_RevertWhen_IndexerIsNotAllocationOwner( - uint256 tokens - ) public useIndexer useAllocation(tokens) { - IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; - // Setup new indexer - address newIndexer = makeAddr("newIndexer"); - _createAndStartAllocation(newIndexer, tokens); - bytes memory data = abi.encode(allocationID, bytes32("POI1")); - // Attempt to collect from other indexer's allocation - vm.expectRevert( - abi.encodeWithSelector(ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, newIndexer, allocationID) - ); - subgraphService.collect(newIndexer, paymentType, data); - } } diff --git a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol new file mode 100644 index 000000000..d51f9ea4b --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; + +import { ISubgraphService } from "../../../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "../../SubgraphService.t.sol"; + +contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function test_SubgraphService_Collect_Indexing( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory data = abi.encode(allocationID, bytes32("POI")); + _collect(users.indexer, paymentType, data); + } + + function test_SubgraphService_Collect_Indexing_WithDelegation( + uint256 tokens, + uint256 delegationTokens, + uint256 delegationFeeCut + ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { + delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM); + _setDelegationFeeCut( + users.indexer, + address(subgraphService), + // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead + IGraphPayments.PaymentTypes.IndexingFee, + 100_000 + ); + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory data = abi.encode(allocationID, bytes32("POI")); + _collect(users.indexer, paymentType, data); + } + + function test_SubgraphService_Collect_Indexing_RewardsDestination( + uint256 tokens + ) public useIndexer useAllocation(tokens) useRewardsDestination { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory data = abi.encode(allocationID, bytes32("POI")); + _collect(users.indexer, paymentType, data); + } + + function test_subgraphService_Collect_Indexing_MultipleOverTime(uint256 tokens) public useIndexer useAllocation(tokens) { + uint8 numberOfPOIs = 20; + uint256 timeBetweenPOIs = 5 days; + + for (uint8 i = 0; i < numberOfPOIs; i++) { + // Skip forward + skip(timeBetweenPOIs); + + resetPrank(users.indexer); + + bytes memory data = abi.encode(allocationID, bytes32("POI")); + _collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data); + } + } + + function test_subgraphService_Collect_Indexing_MultipleOverTime_WithDelegation( + uint256 tokens, + uint256 delegationTokens, + uint256 delegationFeeCut + ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { + delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM); + _setDelegationFeeCut( + users.indexer, + address(subgraphService), + // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead + IGraphPayments.PaymentTypes.IndexingFee, + 100_000 + ); + + uint8 numberOfPOIs = 20; + uint256 timeBetweenPOIs = 5 days; + for (uint8 i = 0; i < numberOfPOIs; i++) { + // Skip forward + skip(timeBetweenPOIs); + + resetPrank(users.indexer); + + bytes memory data = abi.encode(allocationID, bytes32("POI")); + _collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data); + } + } + + function test_SubgraphService_Collect_Indexing_RevertWhen_OverAllocated(uint256 tokens) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens * 2, 10_000_000_000 ether); + + // setup allocation + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + bytes memory data = _createSubgraphAllocationData(users.indexer, subgraphDeployment, allocationIDPrivateKey, tokens); + _startService(users.indexer, data); + + // thaw some tokens to become over allocated + staking.thaw(users.indexer, address(subgraphService), tokens / 2); + + // this collection should close the allocation + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory collectData = abi.encode(allocationID, bytes32("POI")); + _collect(users.indexer, paymentType, collectData); + } + + function test_SubgraphService_Collect_Indexing_RevertWhen_IndexerIsNotAllocationOwner( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + bytes memory data = abi.encode(allocationID, bytes32("POI")); + // Attempt to collect from other indexer's allocation + vm.expectRevert( + abi.encodeWithSelector(ISubgraphService.SubgraphServiceAllocationNotAuthorized.selector, newIndexer, allocationID) + ); + subgraphService.collect(newIndexer, paymentType, data); + } +} diff --git a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol new file mode 100644 index 000000000..9e20ad352 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +// import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; +import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; +import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; + +import { ISubgraphService } from "../../../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "../../SubgraphService.t.sol"; + +contract SubgraphServiceRegisterTest is SubgraphServiceTest { + using PPMMath for uint128; + using PPMMath for uint256; + + address signer; + uint256 signerPrivateKey; + + /* + * HELPERS + */ + + function _getQueryFeeEncodedData(address indexer, uint128 tokens) private view returns (bytes memory) { + ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(indexer, tokens); + bytes32 messageHash = tapCollector.encodeRAV(rav); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, messageHash); + bytes memory signature = abi.encodePacked(r, s, v); + ITAPCollector.SignedRAV memory signedRAV = ITAPCollector.SignedRAV(rav, signature); + return abi.encode(signedRAV); + } + + function _getRAV( + address indexer, + uint128 tokens + ) private view returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { + return + ITAPCollector.ReceiptAggregateVoucher({ + dataService: address(subgraphService), + serviceProvider: indexer, + timestampNs: 0, + valueAggregate: tokens, + metadata: abi.encode(allocationID) + }); + } + + function _approveCollector(uint256 tokens) private { + address msgSender; + (, msgSender, ) = vm.readCallers(); + resetPrank(signer); + mint(signer, tokens); + escrow.approveCollector(address(tapCollector), tokens); + token.approve(address(escrow), tokens); + escrow.deposit(users.indexer, tokens); + resetPrank(msgSender); + } + + /* + * SET UP + */ + + function setUp() public virtual override { + super.setUp(); + (signer, signerPrivateKey) = makeAddrAndKey("signer"); + vm.label({ account: signer, newLabel: "signer" }); + } + + /* + * TESTS + */ + + function testCollect_QueryFees_ONLY_THIS( + uint256 tokensAllocated, + uint256 tokensPayment + ) public useIndexer useAllocation(tokensAllocated) { + vm.assume(tokensAllocated > minimumProvisionTokens * stakeToFeesRatio); + uint256 maxTokensPayment = tokensAllocated / stakeToFeesRatio > type(uint128).max + ? type(uint128).max + : tokensAllocated / stakeToFeesRatio; + tokensPayment = bound(tokensPayment, minimumProvisionTokens, maxTokensPayment); + + _approveCollector(tokensPayment); + + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokensPayment)); + _collect(users.indexer, IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testCollect_MultipleQueryFees( + uint256 tokensAllocated, + uint256 numPayments + ) public useIndexer useAllocation(tokensAllocated) { + vm.assume(tokensAllocated > minimumProvisionTokens * stakeToFeesRatio); + numPayments = bound(numPayments, 1, 10); + uint256 tokensPayment = tokensAllocated / stakeToFeesRatio / numPayments; + + _approveCollector(tokensAllocated); + + uint256 accTokensPayment = 0; + for (uint i = 0; i < numPayments; i++) { + accTokensPayment = accTokensPayment + tokensPayment; + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(accTokensPayment)); + _collect(users.indexer, IGraphPayments.PaymentTypes.QueryFee, data); + } + } + + function testCollect_RevertWhen_NotAuthorized(uint256 tokens) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); + resetPrank(users.operator); + vm.expectRevert( + abi.encodeWithSelector( + ProvisionManager.ProvisionManagerNotAuthorized.selector, + users.operator, + users.indexer + ) + ); + subgraphService.collect(users.indexer, paymentType, data); + } + + function testCollect_QueryFees_RevertWhen_IndexerIsNotAllocationOwner( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + + // This data is for user.indexer allocationId + bytes memory data = _getQueryFeeEncodedData(newIndexer, uint128(tokens)); + + resetPrank(newIndexer); + vm.expectRevert( + abi.encodeWithSelector( + ISubgraphService.SubgraphServiceInvalidRAV.selector, + newIndexer, + users.indexer + ) + ); + subgraphService.collect(newIndexer, paymentType, data); + } + + function testCollect_QueryFees_RevertWhen_CollectingOtherIndexersFees( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.QueryFee; + // Setup new indexer + address newIndexer = makeAddr("newIndexer"); + _createAndStartAllocation(newIndexer, tokens); + bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokens)); + vm.expectRevert( + abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerMismatch.selector, users.indexer, newIndexer) + ); + subgraphService.collect(newIndexer, paymentType, data); + } +} diff --git a/packages/subgraph-service/test/subgraphService/provider/register.t.sol b/packages/subgraph-service/test/subgraphService/provider/register.t.sol index e42e152f7..8e3d0577e 100644 --- a/packages/subgraph-service/test/subgraphService/provider/register.t.sol +++ b/packages/subgraph-service/test/subgraphService/provider/register.t.sol @@ -3,65 +3,54 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; -contract SubgraphServiceRegisterTest is SubgraphServiceTest { +contract SubgraphServiceProviderRegisterTest is SubgraphServiceTest { /* * TESTS */ - function testRegister_Indexer(uint256 tokens) public useIndexer { + function test_SubgraphService_Provider_Register(uint256 tokens) public useIndexer { tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - _createProvision(tokens); + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); - vm.expectEmit(address(subgraphService)); - emit IDataService.ServiceProviderRegistered( - users.indexer, - data - ); - subgraphService.register(users.indexer, data); - - uint256 registeredAt; - string memory url; - string memory geoHash; - (registeredAt, url, geoHash) = subgraphService.indexers(users.indexer); - assertEq(registeredAt, block.timestamp); - assertEq(url, "url"); - assertEq(geoHash, "geoHash"); + _register(users.indexer, data); } - function testRegister_RevertIf_AlreadyRegistered( + function test_SubgraphService_Provider_Register_RevertIf_AlreadyRegistered( uint256 tokens ) public useIndexer useAllocation(tokens) { vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceIndexerAlreadyRegistered.selector)); - _registerIndexer(users.rewardsDestination); + bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); + subgraphService.register(users.indexer, data); } - function testRegister_RevertWhen_InvalidProvision() public useIndexer { + function test_SubgraphService_Provider_Register_RevertWhen_InvalidProvision() public useIndexer { vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerProvisionNotFound.selector, users.indexer )); - _registerIndexer(users.rewardsDestination); + bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); + subgraphService.register(users.indexer, data); } - function testRegister_RevertWhen_NotAuthorized() public { + function test_SubgraphService_Provider_Register_RevertWhen_NotAuthorized() public { resetPrank(users.operator); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, users.operator, users.indexer )); - _registerIndexer(users.rewardsDestination); + bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); + subgraphService.register(users.indexer, data); } - function testRegister_RevertWhen_InvalidProvisionValues(uint256 tokens) public useIndexer { + function test_SubgraphService_Provider_Register_RevertWhen_InvalidProvisionValues(uint256 tokens) public useIndexer { tokens = bound(tokens, 1, minimumProvisionTokens - 1); - _createProvision(tokens); + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerInvalidValue.selector, @@ -70,20 +59,20 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { minimumProvisionTokens, maximumProvisionTokens )); - _registerIndexer(address(0)); + subgraphService.register(users.indexer, abi.encode("url", "geoHash", address(0))); } - function testRegister_RevertIf_EmptyUrl(uint256 tokens) public useIndexer { + function test_SubgraphService_Provider_Register_RevertIf_EmptyUrl(uint256 tokens) public useIndexer { tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - _createProvision(tokens); + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); bytes memory data = abi.encode("", "geoHash", users.rewardsDestination); vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceEmptyUrl.selector)); subgraphService.register(users.indexer, data); } - function testRegister_RevertIf_EmptyGeohash(uint256 tokens) public useIndexer { + function test_SubgraphService_Provider_Register_RevertIf_EmptyGeohash(uint256 tokens) public useIndexer { tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - _createProvision(tokens); + _createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod); bytes memory data = abi.encode("url", "", users.rewardsDestination); vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceEmptyGeohash.selector)); subgraphService.register(users.indexer, data); diff --git a/packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol b/packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol new file mode 100644 index 000000000..3926bc362 --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "forge-std/Test.sol"; + +import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; + +contract SubgraphServiceProviderRewardsDestinationTest is SubgraphServiceTest { + + /* + * TESTS + */ + + function test_SubgraphService_Provider_RewardsDestination_Set( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Should be able to use new address + _setRewardsDestination(users.rewardsDestination); + + // Should be able to set back to address zero + _setRewardsDestination(address(0)); + } +} diff --git a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol index 8e98078c6..9fdb0b76f 100644 --- a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol +++ b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol @@ -14,13 +14,28 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { * TESTS */ - function testAccept_Provision(uint256 tokens) public useIndexer useAllocation(tokens) { - vm.expectEmit(address(subgraphService)); - emit IDataService.ProvisionAccepted(users.indexer); - subgraphService.acceptProvision(users.indexer, ""); + function test_SubgraphService_Provision_Accept( + uint256 tokens, + uint32 newVerifierCut, + uint64 newDisputePeriod + ) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + vm.assume(newVerifierCut >= fishermanRewardPercentage); + vm.assume(newVerifierCut <= MAX_PPM); + vm.assume(newDisputePeriod >= disputePeriod); + + // Setup indexer + _createProvision(users.indexer, tokens, fishermanRewardPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + // Update parameters with new values + _setProvisionParameters(users.indexer, address(subgraphService), newVerifierCut, newDisputePeriod); + + // Accept provision and check parameters + _acceptProvision(users.indexer, ""); } - function testAccept_RevertWhen_NotRegistered() public useIndexer { + function test_SubgraphService_Provision_Accept_RevertWhen_NotRegistered() public useIndexer { vm.expectRevert(abi.encodeWithSelector( ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, users.indexer @@ -28,7 +43,7 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { subgraphService.acceptProvision(users.indexer, ""); } - function testAccept_RevertWhen_NotAuthorized() public { + function test_SubgraphService_Provision_Accept_RevertWhen_NotAuthorized() public { resetPrank(users.operator); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, @@ -37,4 +52,54 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { )); subgraphService.acceptProvision(users.indexer, ""); } + + function test_SubgraphService_Provision_Accept_RevertIf_InvalidVerifierCut( + uint256 tokens, + uint32 newVerifierCut + ) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + vm.assume(newVerifierCut > MAX_PPM); + + // Setup indexer + _createProvision(users.indexer, tokens, fishermanRewardPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + // Update parameters with new values + _setProvisionParameters(users.indexer, address(subgraphService), newVerifierCut, disputePeriod); + + // Should revert since newVerifierCut is invalid + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerInvalidValue.selector, + "maxVerifierCut", + newVerifierCut, + fishermanRewardPercentage, + MAX_PPM + )); + subgraphService.acceptProvision(users.indexer, ""); + } + + function test_SubgraphService_Provision_Accept_RevertIf_InvalidDisputePeriod( + uint256 tokens, + uint64 newDisputePeriod + ) public useIndexer { + tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); + vm.assume(newDisputePeriod < disputePeriod); + + // Setup indexer + _createProvision(users.indexer, tokens, fishermanRewardPercentage, disputePeriod); + _register(users.indexer, abi.encode("url", "geoHash", address(0))); + + // Update parameters with new values + _setProvisionParameters(users.indexer, address(subgraphService), fishermanRewardPercentage, newDisputePeriod); + + // Should revert since newDisputePeriod is invalid + vm.expectRevert(abi.encodeWithSelector( + ProvisionManager.ProvisionManagerInvalidValue.selector, + "thawingPeriod", + newDisputePeriod, + disputePeriod, + type(uint64).max + )); + subgraphService.acceptProvision(users.indexer, ""); + } } diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index b28362653..e20d1fc72 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -3,10 +3,11 @@ pragma solidity 0.8.26; abstract contract Constants { uint256 internal constant MAX_TOKENS = 10_000_000_000 ether; + uint256 internal constant MAX_PPM = 1_000_000; // Dispute Manager uint64 internal constant disputePeriod = 300; // 5 minutes uint256 internal constant disputeDeposit = 100 ether; // 100 GRT - uint32 internal constant fishermanRewardPercentage = 100000; // 10% + uint32 internal constant fishermanRewardPercentage = 500000; // 50% uint32 internal constant maxSlashingPercentage = 500000; // 50% // Subgraph Service uint256 internal constant minimumProvisionTokens = 1000 ether; From 4387c6cdc7cf437e75b46d3af3f1d88aa1fdb925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 9 Sep 2024 16:23:36 -0300 Subject: [PATCH 200/277] test: wip refactor unit tests for staking fns (#1021) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: wip refactor unit tests for staking fns Signed-off-by: Tomás Migone * test: refactor unstake tests passing Signed-off-by: Tomás Migone * test: refactor withdraw tests Signed-off-by: Tomás Migone * test: refactor add to provision Signed-off-by: Tomás Migone * test: wip thaw refactor Signed-off-by: Tomás Migone * test: refactor thaw tests Signed-off-by: Tomás Migone * test: refactor deprovision test Signed-off-by: Tomás Migone * test: refactor reprovision tests Signed-off-by: Tomás Migone * test: refactor provision parameters functions Signed-off-by: Tomás Migone * test: refactor provision tests Signed-off-by: Tomás Migone * test: refactor operator tests Signed-off-by: Tomás Migone * chore: update some configs Signed-off-by: Tomás Migone * test: wip refactor of delegation tests Signed-off-by: Tomás Migone * test: refactor service provider tests Signed-off-by: Tomás Migone * test: refactor delegation tests Signed-off-by: Tomás Migone * test: refactor governance tests Signed-off-by: Tomás Migone * test: refactor ttools tests Signed-off-by: Tomás Migone * test: refactor slash test Signed-off-by: Tomás Migone * test: refactor legacy allocation tests wip Signed-off-by: Tomás Migone * test: refacto allocation close tests Signed-off-by: Tomás Migone * test: refactor collect allocation tests Signed-off-by: Tomás Migone * fix: remove comments Signed-off-by: Tomás Migone * chore: use solidity 0.8.27, remove compilation via ir Signed-off-by: Tomás Migone * chore: use solidity 0.8.27 Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone --- .../contracts/arbitrum/ITokenGateway.sol | 2 +- .../contracts/curation/ICuration.sol | 2 +- .../contracts/epochs/IEpochManager.sol | 2 +- .../contracts/gateway/ICallhookReceiver.sol | 2 +- .../contracts/governance/Controller.sol | 2 +- .../contracts/governance/Governed.sol | 2 +- .../contracts/governance/IController.sol | 2 +- .../contracts/governance/IManaged.sol | 2 +- .../contracts/governance/Pausable.sol | 2 +- .../contracts/l2/staking/IL2StakingBase.sol | 2 +- .../contracts/l2/staking/IL2StakingTypes.sol | 2 +- .../contracts/rewards/IRewardsIssuer.sol | 2 +- .../contracts/rewards/IRewardsManager.sol | 2 +- .../rewards/RewardsManagerStorage.sol | 2 +- .../contracts/contracts/token/IGraphToken.sol | 2 +- .../contracts/upgrades/GraphProxy.sol | 2 +- .../contracts/upgrades/GraphProxyAdmin.sol | 2 +- .../contracts/upgrades/GraphProxyStorage.sol | 2 +- .../contracts/upgrades/GraphUpgradeable.sol | 2 +- .../contracts/upgrades/IGraphProxy.sol | 2 +- .../contracts/contracts/utils/TokenUtils.sol | 2 +- .../contracts/data-service/DataService.sol | 2 +- .../data-service/DataServiceStorage.sol | 2 +- .../extensions/DataServiceFees.sol | 2 +- .../extensions/DataServiceFeesStorage.sol | 2 +- .../extensions/DataServicePausable.sol | 2 +- .../DataServicePausableUpgradeable.sol | 2 +- .../extensions/DataServiceRescuable.sol | 2 +- .../data-service/interfaces/IDataService.sol | 2 +- .../interfaces/IDataServiceFees.sol | 2 +- .../interfaces/IDataServicePausable.sol | 2 +- .../interfaces/IDataServiceRescuable.sol | 2 +- .../libraries/ProvisionTracker.sol | 2 +- .../utilities/ProvisionManager.sol | 2 +- .../utilities/ProvisionManagerStorage.sol | 2 +- .../contracts/interfaces/IGraphPayments.sol | 2 +- .../contracts/interfaces/IGraphProxyAdmin.sol | 2 +- .../contracts/interfaces/IHorizonStaking.sol | 2 +- .../interfaces/IPaymentsCollector.sol | 2 +- .../contracts/interfaces/IPaymentsEscrow.sol | 9 +- .../contracts/interfaces/ITAPCollector.sol | 2 +- .../internal/IHorizonStakingBase.sol | 2 +- .../internal/IHorizonStakingExtension.sol | 2 +- .../internal/IHorizonStakingMain.sol | 2 +- .../internal/IHorizonStakingTypes.sol | 2 +- .../contracts/libraries/Denominations.sol | 2 +- .../contracts/libraries/LibFixedMath.sol | 2 +- .../contracts/libraries/LinkedList.sol | 2 +- .../horizon/contracts/libraries/MathUtils.sol | 2 +- .../horizon/contracts/libraries/PPMMath.sol | 2 +- .../horizon/contracts/libraries/UintRange.sol | 2 +- .../contracts/mocks/ControllerMock.sol | 2 +- .../horizon/contracts/mocks/CurationMock.sol | 2 +- .../contracts/mocks/EpochManagerMock.sol | 2 +- .../horizon/contracts/mocks/MockGRTToken.sol | 2 +- .../contracts/mocks/RewardsManagerMock.sol | 2 +- .../contracts/payments/GraphPayments.sol | 2 +- .../contracts/payments/PaymentsEscrow.sol | 10 +- .../payments/collectors/TAPCollector.sol | 2 +- .../contracts/staking/HorizonStaking.sol | 2 +- .../contracts/staking/HorizonStakingBase.sol | 2 +- .../staking/HorizonStakingExtension.sol | 2 +- .../staking/HorizonStakingStorage.sol | 4 +- .../staking/libraries/ExponentialRebates.sol | 2 +- .../contracts/staking/utilities/Managed.sol | 2 +- .../contracts/utilities/GraphDirectory.sol | 2 +- packages/horizon/foundry.toml | 10 +- packages/horizon/hardhat.config.ts | 3 +- packages/horizon/package.json | 4 +- packages/horizon/test/GraphBase.t.sol | 10 +- .../test/data-service/DataService.t.sol | 29 +- .../data-service/DataServiceUpgradeable.t.sol | 2 +- .../extensions/DataServiceFees.t.sol | 69 +- .../extensions/DataServicePausable.t.sol | 2 +- .../DataServicePausableUpgradeable.t.sol | 2 +- .../implementations/DataServiceBase.sol | 2 +- .../DataServiceBaseUpgradeable.sol | 4 +- .../implementations/DataServiceImpFees.sol | 3 +- .../DataServiceImpPausable.sol | 2 +- .../DataServiceImpPausableUpgradeable.sol | 4 +- .../implementations/DataServiceOverride.sol | 2 +- .../libraries/ProvisionTracker.t.sol | 2 +- .../ProvisionTrackerImplementation.sol | 2 +- .../horizon/test/escrow/GraphEscrow.t.sol | 2 +- packages/horizon/test/escrow/collect.t.sol | 2 +- packages/horizon/test/escrow/collector.t.sol | 2 +- packages/horizon/test/escrow/deposit.t.sol | 2 +- packages/horizon/test/escrow/paused.t.sol | 2 +- packages/horizon/test/escrow/thaw.t.sol | 2 +- packages/horizon/test/escrow/withdraw.t.sol | 2 +- .../horizon/test/libraries/LinkedList.t.sol | 2 +- .../test/libraries/ListImplementation.sol | 4 +- .../horizon/test/payments/GraphPayments.t.sol | 4 +- .../HorizonStakingShared.t.sol | 2235 ++++++++++++++++- .../horizon/test/staking/HorizonStaking.t.sol | 308 +-- .../allocation/HorizonStakingExtension.t.sol | 98 - .../test/staking/allocation/allocation.t.sol | 33 +- .../test/staking/allocation/close.t.sol | 78 +- .../test/staking/allocation/collect.t.sol | 127 +- .../test/staking/delegation/addToPool.t.sol | 8 +- .../test/staking/delegation/delegate.t.sol | 12 +- .../test/staking/delegation/undelegate.t.sol | 18 +- .../test/staking/delegation/withdraw.t.sol | 58 +- .../test/staking/governance/governance.t.sol | 23 +- .../test/staking/operator/locked.t.sol | 8 +- .../test/staking/operator/operator.t.sol | 13 +- .../test/staking/provision/deprovision.t.sol | 74 +- .../test/staking/provision/locked.t.sol | 10 +- .../test/staking/provision/parameters.t.sol | 38 +- .../test/staking/provision/provision.t.sol | 29 +- .../test/staking/provision/reprovision.t.sol | 103 +- .../staking/{thaw => provision}/thaw.t.sol | 54 +- .../serviceProvider/serviceProvider.t.sol | 18 +- .../horizon/test/staking/slash/slash.t.sol | 11 +- .../horizon/test/staking/stake/stake.t.sol | 12 +- .../horizon/test/staking/stake/unstake.t.sol | 149 +- .../horizon/test/staking/stake/withdraw.t.sol | 62 +- .../test/staking/transfer-tools/ttools.t.sol | 112 +- .../test/utilities/GraphDirectory.t.sol | 2 +- .../GraphDirectoryImplementation.sol | 2 +- packages/horizon/test/utils/Constants.sol | 2 +- packages/horizon/test/utils/Users.sol | 2 +- packages/horizon/test/utils/Utils.sol | 2 +- .../contracts/DisputeManager.sol | 2 +- .../contracts/DisputeManagerStorage.sol | 2 +- .../contracts/SubgraphService.sol | 2 +- .../contracts/SubgraphServiceStorage.sol | 2 +- .../contracts/interfaces/IDisputeManager.sol | 2 +- .../contracts/interfaces/ISubgraphService.sol | 2 +- .../contracts/libraries/Allocation.sol | 2 +- .../contracts/libraries/Attestation.sol | 2 +- .../contracts/libraries/LegacyAllocation.sol | 2 +- .../contracts/utilities/AllocationManager.sol | 2 +- .../utilities/AllocationManagerStorage.sol | 2 +- .../utilities/AttestationManager.sol | 2 +- .../utilities/AttestationManagerStorage.sol | 2 +- .../contracts/utilities/Directory.sol | 2 +- packages/subgraph-service/foundry.toml | 10 +- packages/subgraph-service/hardhat.config.ts | 2 +- packages/subgraph-service/package.json | 2 +- .../test/SubgraphBaseTest.t.sol | 2 +- .../test/disputeManager/DisputeManager.t.sol | 63 +- .../constructor/constructor.t.sol | 2 +- .../disputeManager/disputes/disputes.t.sol | 2 +- .../disputes/indexing/accept.t.sol | 2 +- .../disputes/indexing/cancel.t.sol | 2 +- .../disputes/indexing/create.t.sol | 2 +- .../disputes/indexing/draw.t.sol | 2 +- .../disputes/indexing/reject.t.sol | 2 +- .../disputes/query/accept.t.sol | 2 +- .../disputes/query/cancel.t.sol | 2 +- .../disputes/query/create.t.sol | 2 +- .../disputeManager/disputes/query/draw.t.sol | 2 +- .../disputes/query/reject.t.sol | 2 +- .../disputes/queryConflict/accept.t.sol | 2 +- .../disputes/queryConflict/cancel.t.sol | 2 +- .../disputes/queryConflict/create.t.sol | 2 +- .../disputes/queryConflict/draw.t.sol | 2 +- .../disputes/queryConflict/reject.t.sol | 2 +- .../governance/arbitrator.t.sol | 2 +- .../governance/disputeDeposit.t.sol | 2 +- .../governance/fishermanRewardCut.t.sol | 2 +- .../governance/maxSlashingCut.t.sol | 2 +- .../test/mocks/MockCuration.sol | 2 +- .../test/mocks/MockGRTToken.sol | 2 +- .../test/mocks/MockRewardsManager.sol | 2 +- .../test/shared/HorizonStakingShared.t.sol | 2 +- .../test/shared/SubgraphServiceShared.t.sol | 2 +- .../subgraphService/SubgraphService.t.sol | 103 +- .../allocation/closeStale.t.sol | 2 +- .../subgraphService/allocation/resize.t.sol | 2 +- .../subgraphService/allocation/start.t.sol | 2 +- .../subgraphService/allocation/stop.t.sol | 2 +- .../subgraphService/collect/collect.t.sol | 2 +- .../collect/indexing/indexing.t.sol | 2 +- .../subgraphService/collect/query/query.t.sol | 2 +- .../subgraphService/provider/register.t.sol | 2 +- .../provider/rewardsDestination.t.sol | 2 +- .../subgraphService/provision/accept.t.sol | 2 +- .../subgraph-service/test/utils/Constants.sol | 2 +- .../subgraph-service/test/utils/Users.sol | 2 +- .../subgraph-service/test/utils/Utils.sol | 2 +- 182 files changed, 2877 insertions(+), 1437 deletions(-) delete mode 100644 packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol rename packages/horizon/test/staking/{thaw => provision}/thaw.t.sol (58%) diff --git a/packages/contracts/contracts/arbitrum/ITokenGateway.sol b/packages/contracts/contracts/arbitrum/ITokenGateway.sol index 96080858c..3b12e578e 100644 --- a/packages/contracts/contracts/arbitrum/ITokenGateway.sol +++ b/packages/contracts/contracts/arbitrum/ITokenGateway.sol @@ -23,7 +23,7 @@ * */ -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface ITokenGateway { /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated diff --git a/packages/contracts/contracts/curation/ICuration.sol b/packages/contracts/contracts/curation/ICuration.sol index 635b45a0c..fe2f0e929 100644 --- a/packages/contracts/contracts/curation/ICuration.sol +++ b/packages/contracts/contracts/curation/ICuration.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; /** * @title Curation Interface diff --git a/packages/contracts/contracts/epochs/IEpochManager.sol b/packages/contracts/contracts/epochs/IEpochManager.sol index 23c55f15b..c65280d59 100644 --- a/packages/contracts/contracts/epochs/IEpochManager.sol +++ b/packages/contracts/contracts/epochs/IEpochManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface IEpochManager { // -- Configuration -- diff --git a/packages/contracts/contracts/gateway/ICallhookReceiver.sol b/packages/contracts/contracts/gateway/ICallhookReceiver.sol index 0fc27cf23..8d003cb76 100644 --- a/packages/contracts/contracts/gateway/ICallhookReceiver.sol +++ b/packages/contracts/contracts/gateway/ICallhookReceiver.sol @@ -6,7 +6,7 @@ * be allowlisted by the governor, but also implement this interface that contains * the function that will actually be called by the L2GraphTokenGateway. */ -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface ICallhookReceiver { /** diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index a24b96b4e..2b71fd885 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import { IController } from "./IController.sol"; import { IManaged } from "./IManaged.sol"; diff --git a/packages/contracts/contracts/governance/Governed.sol b/packages/contracts/contracts/governance/Governed.sol index c9cf940db..76a3247dd 100644 --- a/packages/contracts/contracts/governance/Governed.sol +++ b/packages/contracts/contracts/governance/Governed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; /** * @title Graph Governance contract diff --git a/packages/contracts/contracts/governance/IController.sol b/packages/contracts/contracts/governance/IController.sol index 093a0303a..6ab72010e 100644 --- a/packages/contracts/contracts/governance/IController.sol +++ b/packages/contracts/contracts/governance/IController.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface IController { function getGovernor() external view returns (address); diff --git a/packages/contracts/contracts/governance/IManaged.sol b/packages/contracts/contracts/governance/IManaged.sol index 59f44dd9a..ff6625d81 100644 --- a/packages/contracts/contracts/governance/IManaged.sol +++ b/packages/contracts/contracts/governance/IManaged.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import { IController } from "./IController.sol"; diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 260d658af..6c5d2fd2c 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; abstract contract Pausable { /** diff --git a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol index 8c0b145de..f5c33c2d0 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; diff --git a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol index 086f88e77..500694e89 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingTypes.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface IL2StakingTypes { /// @dev Message codes for the L1 -> L2 bridge callhook diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol index 4bcfa6ea0..705ce8db8 100644 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface IRewardsIssuer { /** diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index 4030ad2e5..3b6bf3ff6 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface IRewardsManager { /** diff --git a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol index c40ad38f4..ded325593 100644 --- a/packages/contracts/contracts/rewards/RewardsManagerStorage.sol +++ b/packages/contracts/contracts/rewards/RewardsManagerStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import "./IRewardsManager.sol"; import "../governance/Managed.sol"; diff --git a/packages/contracts/contracts/token/IGraphToken.sol b/packages/contracts/contracts/token/IGraphToken.sol index f6f1c00f6..df3b7643f 100644 --- a/packages/contracts/contracts/token/IGraphToken.sol +++ b/packages/contracts/contracts/token/IGraphToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxy.sol b/packages/contracts/contracts/upgrades/GraphProxy.sol index cb52ab1dc..d6fbfac7f 100644 --- a/packages/contracts/contracts/upgrades/GraphProxy.sol +++ b/packages/contracts/contracts/upgrades/GraphProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import { GraphProxyStorage } from "./GraphProxyStorage.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol index 55bbd2176..db8e9dcb3 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import { Governed } from "../governance/Governed.sol"; diff --git a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol index cd076c118..7871e4996 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; /** * @title Graph Proxy Storage diff --git a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol index ffc47aa40..60dfbe888 100644 --- a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol +++ b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import { IGraphProxy } from "./IGraphProxy.sol"; diff --git a/packages/contracts/contracts/upgrades/IGraphProxy.sol b/packages/contracts/contracts/upgrades/IGraphProxy.sol index e81722e3f..4f501ed7c 100644 --- a/packages/contracts/contracts/upgrades/IGraphProxy.sol +++ b/packages/contracts/contracts/upgrades/IGraphProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; interface IGraphProxy { function admin() external returns (address); diff --git a/packages/contracts/contracts/utils/TokenUtils.sol b/packages/contracts/contracts/utils/TokenUtils.sol index a34059a1d..fb125613a 100644 --- a/packages/contracts/contracts/utils/TokenUtils.sol +++ b/packages/contracts/contracts/utils/TokenUtils.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.7.6 || 0.8.26; +pragma solidity ^0.7.6 || 0.8.27; import "../token/IGraphToken.sol"; diff --git a/packages/horizon/contracts/data-service/DataService.sol b/packages/horizon/contracts/data-service/DataService.sol index c87cf5e40..8a06ad4ea 100644 --- a/packages/horizon/contracts/data-service/DataService.sol +++ b/packages/horizon/contracts/data-service/DataService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataService } from "./interfaces/IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/DataServiceStorage.sol b/packages/horizon/contracts/data-service/DataServiceStorage.sol index 03b060515..a0271443c 100644 --- a/packages/horizon/contracts/data-service/DataServiceStorage.sol +++ b/packages/horizon/contracts/data-service/DataServiceStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; abstract contract DataServiceV1Storage { /// @dev Gap to allow adding variables in future upgrades diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index bcec6f828..e0ea587f4 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol index 483b67b80..cb4f908dc 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFeesStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index 404876dc6..4d88cb72e 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataServicePausable } from "../interfaces/IDataServicePausable.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol index 53003ebfc..52f27d9c4 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataServicePausable } from "../interfaces/IDataServicePausable.sol"; diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 96fae4c26..081950b8d 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index 258fc336c..b7e1028f0 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index 5e84863e6..483f11274 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataService } from "./IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol index 04e931749..bd27ca848 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServicePausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataService } from "./IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index ba21f3019..811d3b92e 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataService } from "./IDataService.sol"; diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index 08ac970bb..fef392302 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index ef7c9bcf1..d1cf94287 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IHorizonStaking } from "../../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol index 8649055db..0a6bed2be 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title Storage layout for the {ProvisionManager} helper contract. diff --git a/packages/horizon/contracts/interfaces/IGraphPayments.sol b/packages/horizon/contracts/interfaces/IGraphPayments.sol index ab89c94f8..f446d6f52 100644 --- a/packages/horizon/contracts/interfaces/IGraphPayments.sol +++ b/packages/horizon/contracts/interfaces/IGraphPayments.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title Interface for the {GraphPayments} contract diff --git a/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol b/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol index 6bc063057..de812fa87 100644 --- a/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol +++ b/packages/horizon/contracts/interfaces/IGraphProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title IGraphProxyAdmin diff --git a/packages/horizon/contracts/interfaces/IHorizonStaking.sol b/packages/horizon/contracts/interfaces/IHorizonStaking.sol index 1cf1b6283..e38c3e451 100644 --- a/packages/horizon/contracts/interfaces/IHorizonStaking.sol +++ b/packages/horizon/contracts/interfaces/IHorizonStaking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IHorizonStakingTypes } from "./internal/IHorizonStakingTypes.sol"; import { IHorizonStakingMain } from "./internal/IHorizonStakingMain.sol"; diff --git a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol index 176f6284b..bcd67df0a 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphPayments } from "./IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 7ab5ff023..4b98cf0a5 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphPayments } from "./IGraphPayments.sol"; @@ -84,12 +84,7 @@ interface IPaymentsEscrow { * @param tokens The amount of tokens being thawed * @param thawEndTimestamp The timestamp at which the thawing period ends */ - event Thaw( - address indexed payer, - address indexed receiver, - uint256 tokens, - uint256 thawEndTimestamp - ); + event Thaw(address indexed payer, address indexed receiver, uint256 tokens, uint256 thawEndTimestamp); /** * @notice Emitted when a payer withdraws funds from the escrow for a payer-receiver pair diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 28561e2ce..e7b5bc4fd 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IPaymentsCollector } from "./IPaymentsCollector.sol"; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol index 522ddf44e..e221dc2cf 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol"; import { IGraphPayments } from "../IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 2df5cd82a..6e29cb5c9 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index bbbfa07b6..418459d9f 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index 5c2f3f5e7..eef8098e6 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /* solhint-disable var-name-mixedcase */ // TODO: create custom var-name-mixedcase diff --git a/packages/horizon/contracts/libraries/Denominations.sol b/packages/horizon/contracts/libraries/Denominations.sol index fe5cf2d05..675194b1e 100644 --- a/packages/horizon/contracts/libraries/Denominations.sol +++ b/packages/horizon/contracts/libraries/Denominations.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title Denominations library diff --git a/packages/horizon/contracts/libraries/LibFixedMath.sol b/packages/horizon/contracts/libraries/LibFixedMath.sol index 1a941ed11..f23329b5e 100644 --- a/packages/horizon/contracts/libraries/LibFixedMath.sol +++ b/packages/horizon/contracts/libraries/LibFixedMath.sol @@ -18,7 +18,7 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.8.26; +pragma solidity 0.8.27; // solhint-disable indent /// @dev Signed, fixed-point, 127-bit precision math library. diff --git a/packages/horizon/contracts/libraries/LinkedList.sol b/packages/horizon/contracts/libraries/LinkedList.sol index 13607e257..aa72b3fcf 100644 --- a/packages/horizon/contracts/libraries/LinkedList.sol +++ b/packages/horizon/contracts/libraries/LinkedList.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title LinkedList library diff --git a/packages/horizon/contracts/libraries/MathUtils.sol b/packages/horizon/contracts/libraries/MathUtils.sol index a5ad3f41a..1a5599fb6 100644 --- a/packages/horizon/contracts/libraries/MathUtils.sol +++ b/packages/horizon/contracts/libraries/MathUtils.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title MathUtils Library diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index b02230628..5bd636add 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title PPMMath library diff --git a/packages/horizon/contracts/libraries/UintRange.sol b/packages/horizon/contracts/libraries/UintRange.sol index 12fe10176..b2caf779c 100644 --- a/packages/horizon/contracts/libraries/UintRange.sol +++ b/packages/horizon/contracts/libraries/UintRange.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title UintRange library diff --git a/packages/horizon/contracts/mocks/ControllerMock.sol b/packages/horizon/contracts/mocks/ControllerMock.sol index 82673dca6..557b1eff6 100644 --- a/packages/horizon/contracts/mocks/ControllerMock.sol +++ b/packages/horizon/contracts/mocks/ControllerMock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IController } from "@graphprotocol/contracts/contracts/governance/IController.sol"; import { IManaged } from "@graphprotocol/contracts/contracts/governance/IManaged.sol"; diff --git a/packages/horizon/contracts/mocks/CurationMock.sol b/packages/horizon/contracts/mocks/CurationMock.sol index 402a07e4c..996f971b1 100644 --- a/packages/horizon/contracts/mocks/CurationMock.sol +++ b/packages/horizon/contracts/mocks/CurationMock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { MockGRTToken } from "./MockGRTToken.sol"; diff --git a/packages/horizon/contracts/mocks/EpochManagerMock.sol b/packages/horizon/contracts/mocks/EpochManagerMock.sol index b76714e50..12f694a5e 100644 --- a/packages/horizon/contracts/mocks/EpochManagerMock.sol +++ b/packages/horizon/contracts/mocks/EpochManagerMock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; diff --git a/packages/horizon/contracts/mocks/MockGRTToken.sol b/packages/horizon/contracts/mocks/MockGRTToken.sol index 1d5649f29..235999ae5 100644 --- a/packages/horizon/contracts/mocks/MockGRTToken.sol +++ b/packages/horizon/contracts/mocks/MockGRTToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/horizon/contracts/mocks/RewardsManagerMock.sol b/packages/horizon/contracts/mocks/RewardsManagerMock.sol index 2388d99b6..272584ca4 100644 --- a/packages/horizon/contracts/mocks/RewardsManagerMock.sol +++ b/packages/horizon/contracts/mocks/RewardsManagerMock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { MockGRTToken } from "./MockGRTToken.sol"; diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index 4072c2616..b7cb34db7 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 5045be86d..5d0694346 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IGraphPayments } from "../interfaces/IGraphPayments.sol"; @@ -18,12 +18,7 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; * for payments made through the payments protocol for services provided * via a Graph Horizon data service. */ -contract PaymentsEscrow is - Initializable, - MulticallUpgradeable, - GraphDirectory, - IPaymentsEscrow -{ +contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, IPaymentsEscrow { using TokenUtils for IGraphToken; /// @notice Authorization details for payer-collector pairs @@ -73,7 +68,6 @@ contract PaymentsEscrow is WITHDRAW_ESCROW_THAWING_PERIOD = withdrawEscrowThawingPeriod; } - /** * @notice Initialize the contract */ diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index e385667c7..f3d67e819 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphPayments } from "../../interfaces/IGraphPayments.sol"; import { ITAPCollector } from "../../interfaces/ITAPCollector.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index e6cc98315..74b2d8d09 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingMain } from "../interfaces/internal/IHorizonStakingMain.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 722a2f061..b3e94c7ea 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; import { IHorizonStakingBase } from "../interfaces/internal/IHorizonStakingBase.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 1f6843d53..ba7eb3a5b 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index 2b58b02c7..ff515962a 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IHorizonStakingExtension } from "../interfaces/internal/IHorizonStakingExtension.sol"; import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; @@ -105,7 +105,7 @@ abstract contract HorizonStakingV1Storage { /// @dev Operator allow list (legacy) /// Only used when the verifier is the subgraph data service. - mapping(address legacyOperator => mapping(address serviceProvider => bool authorized)) internal _legacyOperatorAuth; + mapping(address serviceProvider => mapping(address legacyOperator => bool authorized)) internal _legacyOperatorAuth; // -- Asset Holders -- diff --git a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol index 1f7f0b3d2..cda9bf247 100644 --- a/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol +++ b/packages/horizon/contracts/staking/libraries/ExponentialRebates.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { LibFixedMath } from "../../libraries/LibFixedMath.sol"; diff --git a/packages/horizon/contracts/staking/utilities/Managed.sol b/packages/horizon/contracts/staking/utilities/Managed.sol index 4d8e77b4f..44d0ad81b 100644 --- a/packages/horizon/contracts/staking/utilities/Managed.sol +++ b/packages/horizon/contracts/staking/utilities/Managed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { GraphDirectory } from "../../utilities/GraphDirectory.sol"; diff --git a/packages/horizon/contracts/utilities/GraphDirectory.sol b/packages/horizon/contracts/utilities/GraphDirectory.sol index b63bcdeab..c24a7984d 100644 --- a/packages/horizon/contracts/utilities/GraphDirectory.sol +++ b/packages/horizon/contracts/utilities/GraphDirectory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "../interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/foundry.toml b/packages/horizon/foundry.toml index a1826d45c..56cb8a0b6 100644 --- a/packages/horizon/foundry.toml +++ b/packages/horizon/foundry.toml @@ -6,12 +6,4 @@ test = 'test' cache_path = 'cache_forge' fs_permissions = [{ access = "read", path = "./"}] optimizer = true -optimizer-runs = 200 -via_ir = true - -[profile.lite] -optimizer = false -optimizer-runs = 1 - -[profile.lite.optimizer_details.yulDetails] -optimizerSteps = ':' \ No newline at end of file +optimizer_runs = 200 \ No newline at end of file diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index fa73c9643..de221c723 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -7,9 +7,8 @@ import { HardhatUserConfig } from 'hardhat/config' const config: HardhatUserConfig = { solidity: { - version: '0.8.26', + version: '0.8.27', settings: { - viaIR: true, optimizer: { enabled: true, runs: 200, diff --git a/packages/horizon/package.json b/packages/horizon/package.json index a214e1d0a..064e7e1db 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -9,8 +9,8 @@ "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", - "build": "forge build && hardhat compile", - "test": "FOUNDRY_PROFILE=lite forge test -vvv && hardhat test" + "build": "forge build contracts && hardhat compile", + "test": "FOUNDRY_PROFILE=test forge test -vvv && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 6236d00dd..3c2375b8d 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -14,6 +14,7 @@ import { GraphPayments } from "contracts/payments/GraphPayments.sol"; import { IHorizonStaking } from "contracts/interfaces/IHorizonStaking.sol"; import { HorizonStaking } from "contracts/staking/HorizonStaking.sol"; import { HorizonStakingExtension } from "contracts/staking/HorizonStakingExtension.sol"; +import { IHorizonStakingTypes } from "contracts/interfaces/internal/IHorizonStakingTypes.sol"; import { MockGRTToken } from "../contracts/mocks/MockGRTToken.sol"; import { EpochManagerMock } from "../contracts/mocks/EpochManagerMock.sol"; import { RewardsManagerMock } from "../contracts/mocks/RewardsManagerMock.sol"; @@ -22,8 +23,7 @@ import { Constants } from "./utils/Constants.sol"; import { Users } from "./utils/Users.sol"; import { Utils } from "./utils/Utils.sol"; -abstract contract GraphBaseTest is Utils, Constants { - +abstract contract GraphBaseTest is IHorizonStakingTypes, Utils, Constants { /* * VARIABLES */ @@ -54,10 +54,6 @@ abstract contract GraphBaseTest is Utils, Constants { Users internal users; - /* Constants */ - - Constants public constants; - /* * SET UP */ diff --git a/packages/horizon/test/data-service/DataService.t.sol b/packages/horizon/test/data-service/DataService.t.sol index 98f7aadb3..c535c6dea 100644 --- a/packages/horizon/test/data-service/DataService.t.sol +++ b/packages/horizon/test/data-service/DataService.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; @@ -69,7 +69,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataService.setProvisionTokensRange(dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); tokens = bound(tokens, dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); - _createProvision(address(dataService), tokens, 0, 0); + _createProvision(users.indexer, address(dataService), tokens, 0, 0); dataService.checkProvisionTokens(users.indexer); } @@ -81,7 +81,7 @@ contract DataServiceTest is HorizonStakingSharedTest { ); // this checker accepts provisions with any amount of tokens - _createProvision(address(dataServiceOverride), tokens, 0, 0); + _createProvision(users.indexer, address(dataServiceOverride), tokens, 0, 0); dataServiceOverride.checkProvisionTokens(users.indexer); } @@ -89,7 +89,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataService.setProvisionTokensRange(dataService.PROVISION_TOKENS_MIN(), dataService.PROVISION_TOKENS_MAX()); tokens = bound(tokens, 1, dataService.PROVISION_TOKENS_MIN() - 1); - _createProvision(address(dataService), tokens, 0, 0); + _createProvision(users.indexer, address(dataService), tokens, 0, 0); vm.expectRevert( abi.encodeWithSelector( ProvisionManager.ProvisionManagerInvalidValue.selector, @@ -142,7 +142,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); verifierCut = uint32(bound(verifierCut, dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX())); - _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); + _createProvision(users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); dataService.checkProvisionParameters(users.indexer, false); } @@ -151,7 +151,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataServiceOverride.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); // this checker accepts provisions with any verifier cut range - _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); + _createProvision(users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); dataServiceOverride.checkProvisionParameters(users.indexer, false); } @@ -159,7 +159,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataService.setVerifierCutRange(dataService.VERIFIER_CUT_MIN(), dataService.VERIFIER_CUT_MAX()); verifierCut = uint32(bound(verifierCut, 0, dataService.VERIFIER_CUT_MIN() - 1)); - _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); + _createProvision(users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), verifierCut, 0); vm.expectRevert( abi.encodeWithSelector( ProvisionManager.ProvisionManagerInvalidValue.selector, @@ -205,7 +205,7 @@ contract DataServiceTest is HorizonStakingSharedTest { bound(thawingPeriod, dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()) ); - _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); + _createProvision(users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); dataService.checkProvisionParameters(users.indexer, false); } @@ -214,7 +214,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataServiceOverride.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); // this checker accepts provisions with any verifier cut range - _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); + _createProvision(users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); dataServiceOverride.checkProvisionParameters(users.indexer, false); } @@ -222,7 +222,7 @@ contract DataServiceTest is HorizonStakingSharedTest { dataService.setThawingPeriodRange(dataService.THAWING_PERIOD_MIN(), dataService.THAWING_PERIOD_MAX()); thawingPeriod = uint32(bound(thawingPeriod, 0, dataService.THAWING_PERIOD_MIN() - 1)); - _createProvision(address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); + _createProvision(users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), 0, thawingPeriod); vm.expectRevert( abi.encodeWithSelector( ProvisionManager.ProvisionManagerInvalidValue.selector, @@ -255,12 +255,13 @@ contract DataServiceTest is HorizonStakingSharedTest { // stage provision parameter changes _createProvision( + users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), dataService.VERIFIER_CUT_MIN(), dataService.THAWING_PERIOD_MIN() ); - staking.setProvisionParameters(users.indexer, address(dataService), maxVerifierCut, thawingPeriod); + _setProvisionParameters(users.indexer, address(dataService), maxVerifierCut, thawingPeriod); // accept provision parameters if (maxVerifierCut != dataService.VERIFIER_CUT_MIN() || thawingPeriod != dataService.THAWING_PERIOD_MIN()) { @@ -287,12 +288,13 @@ contract DataServiceTest is HorizonStakingSharedTest { // stage provision parameter changes _createProvision( + users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), dataService.VERIFIER_CUT_MIN(), dataService.THAWING_PERIOD_MIN() ); - staking.setProvisionParameters( + _setProvisionParameters( users.indexer, address(dataService), dataService.VERIFIER_CUT_MIN(), @@ -324,12 +326,13 @@ contract DataServiceTest is HorizonStakingSharedTest { // stage provision parameter changes _createProvision( + users.indexer, address(dataService), dataService.PROVISION_TOKENS_MIN(), dataService.VERIFIER_CUT_MIN(), dataService.THAWING_PERIOD_MIN() ); - staking.setProvisionParameters( + _setProvisionParameters( users.indexer, address(dataService), maxVerifierCut, diff --git a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol index c8721260f..be33173f8 100644 --- a/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol +++ b/packages/horizon/test/data-service/DataServiceUpgradeable.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { GraphBaseTest } from "../GraphBase.t.sol"; import { DataServiceBaseUpgradeable } from "./implementations/DataServiceBaseUpgradeable.sol"; diff --git a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol index 4ab1406ae..f6f31d54c 100644 --- a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; import { DataServiceImpFees } from "../implementations/DataServiceImpFees.sol"; @@ -126,20 +126,27 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { } // -- Assertion functions -- - + // use struct to avoid 'stack too deep' error + struct CalcValues_LockStake { + uint256 unlockTimestamp; + uint256 stakeToLock; + bytes32 predictedClaimId; + } function _assert_lockStake(address serviceProvider, uint256 tokens) private { // before state (bytes32 beforeHead, , uint256 beforeNonce, uint256 beforeCount) = dataService.claimsLists(serviceProvider); uint256 beforeLockedStake = dataService.feesProvisionTracker(serviceProvider); // calc - uint256 unlockTimestamp = block.timestamp + dataService.LOCK_DURATION(); - uint256 stakeToLock = tokens * dataService.STAKE_TO_FEES_RATIO(); - bytes32 predictedClaimId = keccak256(abi.encodePacked(address(dataService), serviceProvider, beforeNonce)); + CalcValues_LockStake memory calcValues = CalcValues_LockStake({ + unlockTimestamp: block.timestamp + dataService.LOCK_DURATION(), + stakeToLock: tokens * dataService.STAKE_TO_FEES_RATIO(), + predictedClaimId: keccak256(abi.encodePacked(address(dataService), serviceProvider, beforeNonce)) + }); // it should emit a an event vm.expectEmit(); - emit IDataServiceFees.StakeClaimLocked(serviceProvider, predictedClaimId, stakeToLock, unlockTimestamp); + emit IDataServiceFees.StakeClaimLocked(serviceProvider, calcValues.predictedClaimId, calcValues.stakeToLock, calcValues.unlockTimestamp); dataService.lockStake(serviceProvider, tokens); // after state @@ -149,24 +156,30 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { ); // it should lock the tokens - assertEq(beforeLockedStake + stakeToLock, afterLockedStake); + assertEq(beforeLockedStake + calcValues.stakeToLock, afterLockedStake); // it should create a stake claim (uint256 claimTokens, uint256 createdAt, uint256 releaseAt, bytes32 nextClaim) = dataService.claims( - predictedClaimId + calcValues.predictedClaimId ); - assertEq(claimTokens, stakeToLock); + assertEq(claimTokens, calcValues.stakeToLock); assertEq(createdAt, block.timestamp); - assertEq(releaseAt, unlockTimestamp); + assertEq(releaseAt, calcValues.unlockTimestamp); assertEq(nextClaim, bytes32(0)); // it should update the list assertEq(afterCount, beforeCount + 1); assertEq(afterNonce, beforeNonce + 1); - assertEq(afterHead, beforeCount == 0 ? predictedClaimId : beforeHead); - assertEq(afterTail, predictedClaimId); + assertEq(afterHead, beforeCount == 0 ? calcValues.predictedClaimId : beforeHead); + assertEq(afterTail, calcValues.predictedClaimId); } + // use struct to avoid 'stack too deep' error + struct CalcValues_ReleaseStake { + uint256 claimsCount; + uint256 tokensReleased; + bytes32 head; + } function _assert_releaseStake(address serviceProvider, uint256 n) private { // before state (bytes32 beforeHead, bytes32 beforeTail, uint256 beforeNonce, uint256 beforeCount) = dataService.claimsLists( @@ -177,23 +190,25 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { // calc and set events vm.expectEmit(); - uint256 claimsCount = 0; - uint256 tokensReleased = 0; - bytes32 head = beforeHead; - while (head != bytes32(0) && (claimsCount < n || n == 0)) { - (uint256 claimTokens, , uint256 releaseAt, bytes32 nextClaim) = dataService.claims(head); + CalcValues_ReleaseStake memory calcValues = CalcValues_ReleaseStake({ + claimsCount: 0, + tokensReleased: 0, + head: beforeHead + }); + while (calcValues.head != bytes32(0) && (calcValues.claimsCount < n || n == 0)) { + (uint256 claimTokens, , uint256 releaseAt, bytes32 nextClaim) = dataService.claims(calcValues.head); if (releaseAt > block.timestamp) { break; } - emit IDataServiceFees.StakeClaimReleased(serviceProvider, head, claimTokens, releaseAt); - head = nextClaim; - tokensReleased += claimTokens; - claimsCount++; + emit IDataServiceFees.StakeClaimReleased(serviceProvider, calcValues.head, claimTokens, releaseAt); + calcValues.head = nextClaim; + calcValues.tokensReleased += claimTokens; + calcValues.claimsCount++; } // it should emit a an event - emit IDataServiceFees.StakeClaimsReleased(serviceProvider, claimsCount, tokensReleased); + emit IDataServiceFees.StakeClaimsReleased(serviceProvider, calcValues.claimsCount, calcValues.tokensReleased); dataService.releaseStake(n); // after state @@ -203,17 +218,17 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { uint256 afterLockedStake = dataService.feesProvisionTracker(serviceProvider); // it should release the tokens - assertEq(beforeLockedStake - tokensReleased, afterLockedStake); + assertEq(beforeLockedStake - calcValues.tokensReleased, afterLockedStake); // it should remove the processed claims from the list - assertEq(afterCount, beforeCount - claimsCount); + assertEq(afterCount, beforeCount - calcValues.claimsCount); assertEq(afterNonce, beforeNonce); - if (claimsCount != 0) { + if (calcValues.claimsCount != 0) { assertNotEq(afterHead, beforeHead); } else { assertEq(afterHead, beforeHead); } - assertEq(afterHead, head); - assertEq(afterTail, claimsCount == beforeCount ? bytes32(0) : beforeTail); + assertEq(afterHead, calcValues.head); + assertEq(afterTail, calcValues.claimsCount == beforeCount ? bytes32(0) : beforeTail); } } diff --git a/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol b/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol index c71cace11..111838fe4 100644 --- a/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServicePausable.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; import { DataServiceImpPausable } from "../implementations/DataServiceImpPausable.sol"; diff --git a/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol b/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol index 9f4a8822b..6e58810c1 100644 --- a/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServicePausableUpgradeable.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { GraphBaseTest } from "../../GraphBase.t.sol"; import { DataServiceImpPausableUpgradeable } from "../implementations/DataServiceImpPausableUpgradeable.sol"; diff --git a/packages/horizon/test/data-service/implementations/DataServiceBase.sol b/packages/horizon/test/data-service/implementations/DataServiceBase.sol index b8171e649..d98dd2857 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceBase.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBase.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { DataService } from "../../../contracts/data-service/DataService.sol"; import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; diff --git a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol index fbe2fe211..31309c524 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { DataService } from "../../../contracts/data-service/DataService.sol"; import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; contract DataServiceBaseUpgradeable is DataService { - constructor(address controller) DataService(controller) { + constructor(address controller_) DataService(controller_) { _disableInitializers(); } diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol index ee071c47d..efabda6ff 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { DataService } from "../../../contracts/data-service/DataService.sol"; import { DataServiceFees } from "../../../contracts/data-service/extensions/DataServiceFees.sol"; @@ -25,6 +25,7 @@ contract DataServiceImpFees is DataServiceFees { uint256 amount = abi.decode(data, (uint256)); _releaseStake(serviceProvider, 0); _lockStake(serviceProvider, amount * STAKE_TO_FEES_RATIO, block.timestamp + LOCK_DURATION); + return amount; } function lockStake(address serviceProvider, uint256 amount) external { diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol index 5d49f8873..0ca990ab1 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { DataService } from "../../../contracts/data-service/DataService.sol"; import { DataServicePausable } from "../../../contracts/data-service/extensions/DataServicePausable.sol"; diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol index 5b55d0866..39b2bb26b 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { DataService } from "../../../contracts/data-service/DataService.sol"; import { DataServicePausableUpgradeable } from "../../../contracts/data-service/extensions/DataServicePausableUpgradeable.sol"; import { IGraphPayments } from "./../../../contracts/interfaces/IGraphPayments.sol"; contract DataServiceImpPausableUpgradeable is DataServicePausableUpgradeable { - constructor(address controller) DataService(controller) { + constructor(address controller_) DataService(controller_) { _disableInitializers(); } diff --git a/packages/horizon/test/data-service/implementations/DataServiceOverride.sol b/packages/horizon/test/data-service/implementations/DataServiceOverride.sol index 838be68a5..c5d50ca74 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceOverride.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceOverride.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { DataServiceBase } from "./DataServiceBase.sol"; diff --git a/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol b/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol index a7ec2f614..af147fdd6 100644 --- a/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol +++ b/packages/horizon/test/data-service/libraries/ProvisionTracker.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; import { ProvisionTrackerImplementation } from "./ProvisionTrackerImplementation.sol"; diff --git a/packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol b/packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol index 0093fba72..5c9cf4a6a 100644 --- a/packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol +++ b/packages/horizon/test/data-service/libraries/ProvisionTrackerImplementation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { ProvisionTracker } from "../../../contracts/data-service/libraries/ProvisionTracker.sol"; diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index a510f57bf..2421ea80c 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 1ba403a23..67efcc6e7 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index 5023c38ce..3e5b71bc0 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol index 79b7c3616..3ce341a1a 100644 --- a/packages/horizon/test/escrow/deposit.t.sol +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/paused.t.sol b/packages/horizon/test/escrow/paused.t.sol index 2be37a61b..f6b65aa2b 100644 --- a/packages/horizon/test/escrow/paused.t.sol +++ b/packages/horizon/test/escrow/paused.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 35f501ff3..36808602c 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index f7ffdd1c6..0e5670c7a 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/horizon/test/libraries/LinkedList.t.sol b/packages/horizon/test/libraries/LinkedList.t.sol index 5150b6116..1850cdb47 100644 --- a/packages/horizon/test/libraries/LinkedList.t.sol +++ b/packages/horizon/test/libraries/LinkedList.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/console.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/packages/horizon/test/libraries/ListImplementation.sol b/packages/horizon/test/libraries/ListImplementation.sol index 9c8bbfb60..fda762c6d 100644 --- a/packages/horizon/test/libraries/ListImplementation.sol +++ b/packages/horizon/test/libraries/ListImplementation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { LinkedList } from "../../contracts/libraries/LinkedList.sol"; @@ -34,7 +34,7 @@ contract ListImplementation { return items[_id].next; } - function _processItemAddition(bytes32 _id, bytes memory _acc) internal returns (bool, bytes memory) { + function _processItemAddition(bytes32 _id, bytes memory _acc) internal view returns (bool, bytes memory) { uint256 sum = abi.decode(_acc, (uint256)); sum += items[_id].data; return (false, abi.encode(sum)); // dont break, do delete diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 9d2ef7495..62e582c26 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -60,7 +60,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { uint256 amount, uint256 tokensDataService ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { - tokensDataService = bound(tokensDataService, amount + 1, MAX_STAKING_TOKENS); + tokensDataService = bound(tokensDataService, amount + 1, MAX_STAKING_TOKENS + 1); address escrowAddress = address(escrow); mint(escrowAddress, amount); diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index faf7b8039..d9f300979 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -1,12 +1,35 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; import { GraphBaseTest } from "../../GraphBase.t.sol"; import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol"; +import { IHorizonStakingBase } from "../../../contracts/interfaces/internal/IHorizonStakingBase.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; +import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; +import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; + +import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; +import { MathUtils } from "../../../contracts/libraries/MathUtils.sol"; +import { PPMMath } from "../../../contracts/libraries/PPMMath.sol"; +import { ExponentialRebates } from "../../../contracts/staking/libraries/ExponentialRebates.sol"; abstract contract HorizonStakingSharedTest is GraphBaseTest { + using LinkedList for LinkedList.List; + using PPMMath for uint256; + + event Transfer(address indexed from, address indexed to, uint tokens); + + address internal _allocationId = makeAddr("allocationId"); + bytes32 internal constant _subgraphDeploymentID = keccak256("subgraphDeploymentID"); + uint256 internal constant MAX_ALLOCATION_EPOCHS = 28; + + uint32 internal alphaNumerator = 100; + uint32 internal alphaDenominator = 100; + uint32 internal lambdaNumerator = 60; + uint32 internal lambdaDenominator = 100; + /* * MODIFIERS */ @@ -17,9 +40,17 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { vm.stopPrank(); } - modifier assumeProvisionTokens(uint256 tokens) { - vm.assume(tokens > 0); - vm.assume(tokens <= MAX_STAKING_TOKENS); + modifier useOperator() { + vm.startPrank(users.indexer); + _setOperator(users.operator, subgraphDataServiceAddress, true); + vm.startPrank(users.operator); + _; + vm.stopPrank(); + } + + modifier useStake(uint256 amount) { + vm.assume(amount > 0); + _stake(amount); _; } @@ -43,41 +74,2203 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { } modifier useDelegationFeeCut(IGraphPayments.PaymentTypes paymentType, uint256 cut) { - _setDelegationFeeCut(paymentType, cut); + _setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, cut); + _; + } + + function _useProvision(address dataService, uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) internal { + // use assume instead of bound to avoid the bounding falling out of scope + vm.assume(tokens > 0); + vm.assume(tokens <= MAX_STAKING_TOKENS); + vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); + vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); + + _createProvision(users.indexer, dataService, tokens, maxVerifierCut, thawingPeriod); + } + + modifier useAllocation(uint256 tokens) { + vm.assume(tokens <= MAX_STAKING_TOKENS); + _createAllocation(users.indexer, _allocationId, _subgraphDeploymentID, tokens); + _; + } + + modifier useRebateParameters() { + _setStorage_RebateParameters(alphaNumerator, alphaDenominator, lambdaNumerator, lambdaDenominator); _; } /* - * HELPERS + * HELPERS: these are shortcuts to perform common actions that often involve multiple contract calls */ + function _createProvision( + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) internal { + _stakeTo(serviceProvider, tokens); + _provision(serviceProvider, verifier, tokens, maxVerifierCut, thawingPeriod); + } - function _useProvision( - address dataService, + // This allows setting up contract state with legacy allocations + function _createAllocation( + address serviceProvider, + address allocationId, + bytes32 subgraphDeploymentID, + uint256 tokens + ) internal { + _setStorage_MaxAllocationEpochs(MAX_ALLOCATION_EPOCHS); + + IHorizonStakingExtension.Allocation memory _allocation = IHorizonStakingExtension.Allocation({ + indexer: serviceProvider, + subgraphDeploymentID: subgraphDeploymentID, + tokens: tokens, + createdAtEpoch: block.timestamp, + closedAtEpoch: 0, + collectedFees: 0, + __DEPRECATED_effectiveAllocation: 0, + accRewardsPerAllocatedToken: 0, + distributedRebates: 0 + }); + _setStorage_allocation(_allocation, allocationId, tokens); + + // delegation pool initialized + _setStorage_DelegationPool(serviceProvider, 0, uint32(PPMMath.MAX_PPM), uint32(PPMMath.MAX_PPM)); + + token.transfer(address(staking), tokens); + } + + /* + * ACTIONS: these are individual contract calls wrapped in assertion blocks to ensure they work as expected + */ + function _stake(uint256 tokens) internal { + (, address msgSender, ) = vm.readCallers(); + _stakeTo(msgSender, tokens); + } + + function _stakeTo(address serviceProvider, uint256 tokens) internal { + (, address msgSender, ) = vm.readCallers(); + + // before + uint256 beforeStakingBalance = token.balanceOf(address(staking)); + uint256 beforeSenderBalance = token.balanceOf(msgSender); + ServiceProviderInternal memory beforeServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + + // stakeTo + token.approve(address(staking), tokens); + vm.expectEmit(); + emit IHorizonStakingBase.StakeDeposited(serviceProvider, tokens); + staking.stakeTo(serviceProvider, tokens); + + // after + uint256 afterStakingBalance = token.balanceOf(address(staking)); + uint256 afterSenderBalance = token.balanceOf(msgSender); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + + // assert + assertEq(afterStakingBalance, beforeStakingBalance + tokens); + assertEq(afterSenderBalance, beforeSenderBalance - tokens); + assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked + tokens); + assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned); + assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); + assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeServiceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLockedUntil, + beforeServiceProvider.__DEPRECATED_tokensLockedUntil + ); + } + + function _unstake(uint256 _tokens) internal { + (, address msgSender, ) = vm.readCallers(); + + uint256 deprecatedThawingPeriod = staking.__DEPRECATED_getThawingPeriod(); + + // before + uint256 beforeSenderBalance = token.balanceOf(msgSender); + uint256 beforeStakingBalance = token.balanceOf(address(staking)); + ServiceProviderInternal memory beforeServiceProvider = _getStorage_ServiceProviderInternal(msgSender); + + bool withdrawCalled = beforeServiceProvider.__DEPRECATED_tokensLocked != 0 && + block.number >= beforeServiceProvider.__DEPRECATED_tokensLockedUntil; + + if (deprecatedThawingPeriod != 0 && beforeServiceProvider.__DEPRECATED_tokensLocked > 0) { + deprecatedThawingPeriod = MathUtils.weightedAverageRoundingUp( + MathUtils.diffOrZero( + withdrawCalled ? 0 : beforeServiceProvider.__DEPRECATED_tokensLockedUntil, + block.number + ), + withdrawCalled ? 0 : beforeServiceProvider.__DEPRECATED_tokensLocked, + deprecatedThawingPeriod, + _tokens + ); + } + + // unstake + if (deprecatedThawingPeriod == 0) { + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.StakeWithdrawn(msgSender, _tokens); + } else { + if (withdrawCalled) { + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.StakeWithdrawn(msgSender, beforeServiceProvider.__DEPRECATED_tokensLocked); + } + + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.StakeLocked( + msgSender, + withdrawCalled ? _tokens : beforeServiceProvider.__DEPRECATED_tokensLocked + _tokens, + block.number + deprecatedThawingPeriod + ); + } + staking.unstake(_tokens); + + // after + uint256 afterSenderBalance = token.balanceOf(msgSender); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(msgSender); + + // assert + if (deprecatedThawingPeriod == 0) { + assertEq(afterSenderBalance, _tokens + beforeSenderBalance); + assertEq(afterStakingBalance, beforeStakingBalance - _tokens); + assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked - _tokens); + assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned); + assertEq( + afterServiceProvider.__DEPRECATED_tokensAllocated, + beforeServiceProvider.__DEPRECATED_tokensAllocated + ); + assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeServiceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLockedUntil, + beforeServiceProvider.__DEPRECATED_tokensLockedUntil + ); + } else { + assertEq( + afterServiceProvider.tokensStaked, + withdrawCalled + ? beforeServiceProvider.tokensStaked - beforeServiceProvider.__DEPRECATED_tokensLocked + : beforeServiceProvider.tokensStaked + ); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLocked, + _tokens + (withdrawCalled ? 0 : beforeServiceProvider.__DEPRECATED_tokensLocked) + ); + assertEq(afterServiceProvider.__DEPRECATED_tokensLockedUntil, block.number + deprecatedThawingPeriod); + assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned); + assertEq( + afterServiceProvider.__DEPRECATED_tokensAllocated, + beforeServiceProvider.__DEPRECATED_tokensAllocated + ); + uint256 tokensTransferred = (withdrawCalled ? beforeServiceProvider.__DEPRECATED_tokensLocked : 0); + assertEq(afterSenderBalance, beforeSenderBalance + tokensTransferred); + assertEq(afterStakingBalance, beforeStakingBalance - tokensTransferred); + } + } + + function _withdraw() internal { + (, address msgSender, ) = vm.readCallers(); + + // before + ServiceProviderInternal memory beforeServiceProvider = _getStorage_ServiceProviderInternal(msgSender); + uint256 beforeSenderBalance = token.balanceOf(msgSender); + uint256 beforeStakingBalance = token.balanceOf(address(staking)); + + // withdraw + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.StakeWithdrawn(msgSender, beforeServiceProvider.__DEPRECATED_tokensLocked); + staking.withdraw(); + + // after + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(msgSender); + uint256 afterSenderBalance = token.balanceOf(msgSender); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + + // assert + assertEq(afterSenderBalance - beforeSenderBalance, beforeServiceProvider.__DEPRECATED_tokensLocked); + assertEq(beforeStakingBalance - afterStakingBalance, beforeServiceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.tokensStaked, + beforeServiceProvider.tokensStaked - beforeServiceProvider.__DEPRECATED_tokensLocked + ); + assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned); + assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); + assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, 0); + assertEq(afterServiceProvider.__DEPRECATED_tokensLockedUntil, 0); + } + + function _provision( + address serviceProvider, + address verifier, uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod ) internal { - vm.assume(tokens <= MAX_STAKING_TOKENS); - vm.assume(tokens > 0); - vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); - vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); - _createProvision(dataService, tokens, maxVerifierCut, thawingPeriod); + __provision(serviceProvider, verifier, tokens, maxVerifierCut, thawingPeriod, false); } - function _createProvision( - address dataServiceAddress, + function _provisionLocked( + address serviceProvider, + address verifier, uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod ) internal { + __provision(serviceProvider, verifier, tokens, maxVerifierCut, thawingPeriod, true); + } + + function __provision( + address serviceProvider, + address verifier, + uint256 tokens, + uint32 maxVerifierCut, + uint64 thawingPeriod, + bool locked + ) private { + // before + ServiceProviderInternal memory beforeServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + + // provision + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionCreated(serviceProvider, verifier, tokens, maxVerifierCut, thawingPeriod); + if (locked) { + staking.provisionLocked(serviceProvider, verifier, tokens, maxVerifierCut, thawingPeriod); + } else { + staking.provision(serviceProvider, verifier, tokens, maxVerifierCut, thawingPeriod); + } + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + + // assert + assertEq(afterProvision.tokens, tokens); + assertEq(afterProvision.tokensThawing, 0); + assertEq(afterProvision.sharesThawing, 0); + assertEq(afterProvision.maxVerifierCut, maxVerifierCut); + assertEq(afterProvision.thawingPeriod, thawingPeriod); + assertEq(afterProvision.createdAt, uint64(block.timestamp)); + assertEq(afterProvision.maxVerifierCutPending, maxVerifierCut); + assertEq(afterProvision.thawingPeriodPending, thawingPeriod); + assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked); + assertEq(afterServiceProvider.tokensProvisioned, tokens + beforeServiceProvider.tokensProvisioned); + assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); + assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeServiceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLockedUntil, + beforeServiceProvider.__DEPRECATED_tokensLockedUntil + ); + } + + function _addToProvision(address serviceProvider, address verifier, uint256 tokens) internal { + // before + Provision memory beforeProvision = staking.getProvision(serviceProvider, verifier); + ServiceProviderInternal memory beforeServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + + // addToProvision + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionIncreased(serviceProvider, verifier, tokens); + staking.addToProvision(serviceProvider, verifier, tokens); + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + + // assert + assertEq(afterProvision.tokens, beforeProvision.tokens + tokens); + assertEq(afterProvision.tokensThawing, beforeProvision.tokensThawing); + assertEq(afterProvision.sharesThawing, beforeProvision.sharesThawing); + assertEq(afterProvision.maxVerifierCut, beforeProvision.maxVerifierCut); + assertEq(afterProvision.thawingPeriod, beforeProvision.thawingPeriod); + assertEq(afterProvision.createdAt, beforeProvision.createdAt); + assertEq(afterProvision.maxVerifierCutPending, beforeProvision.maxVerifierCutPending); + assertEq(afterProvision.thawingPeriodPending, beforeProvision.thawingPeriodPending); + assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked); + assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned + tokens); + assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); + assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeServiceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLockedUntil, + beforeServiceProvider.__DEPRECATED_tokensLockedUntil + ); + } + + function _thaw(address serviceProvider, address verifier, uint256 tokens) internal returns (bytes32) { + // before + Provision memory beforeProvision = staking.getProvision(serviceProvider, verifier); + LinkedList.List memory beforeThawRequestList = staking.getThawRequestList( + serviceProvider, + verifier, + serviceProvider + ); + + bytes32 expectedThawRequestId = keccak256( + abi.encodePacked(users.indexer, verifier, users.indexer, beforeThawRequestList.nonce) + ); + uint256 thawingShares = beforeProvision.sharesThawing == 0 + ? tokens + : (beforeProvision.sharesThawing * tokens) / beforeProvision.tokensThawing; + + // thaw + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawRequestCreated( + serviceProvider, + verifier, + serviceProvider, + thawingShares, + uint64(block.timestamp + beforeProvision.thawingPeriod), + expectedThawRequestId + ); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ProvisionThawed(serviceProvider, verifier, tokens); + bytes32 thawRequestId = staking.thaw(serviceProvider, verifier, tokens); + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); + ThawRequest memory afterThawRequest = staking.getThawRequest(thawRequestId); + LinkedList.List memory afterThawRequestList = staking.getThawRequestList( + serviceProvider, + verifier, + serviceProvider + ); + ThawRequest memory afterPreviousTailThawRequest = staking.getThawRequest(beforeThawRequestList.tail); + + // assert + assertEq(afterProvision.tokens, beforeProvision.tokens); + assertEq(afterProvision.tokensThawing, beforeProvision.tokensThawing + tokens); + assertEq(afterProvision.sharesThawing, beforeProvision.sharesThawing + thawingShares); + assertEq(afterProvision.maxVerifierCut, beforeProvision.maxVerifierCut); + assertEq(afterProvision.thawingPeriod, beforeProvision.thawingPeriod); + assertEq(afterProvision.createdAt, beforeProvision.createdAt); + assertEq(afterProvision.maxVerifierCutPending, beforeProvision.maxVerifierCutPending); + assertEq(afterProvision.thawingPeriodPending, beforeProvision.thawingPeriodPending); + assertEq(thawRequestId, expectedThawRequestId); + assertEq(afterThawRequest.shares, thawingShares); + assertEq(afterThawRequest.thawingUntil, block.timestamp + beforeProvision.thawingPeriod); + assertEq(afterThawRequest.next, bytes32(0)); + assertEq( + afterThawRequestList.head, + beforeThawRequestList.count == 0 ? thawRequestId : beforeThawRequestList.head + ); + assertEq(afterThawRequestList.tail, thawRequestId); + assertEq(afterThawRequestList.count, beforeThawRequestList.count + 1); + assertEq(afterThawRequestList.nonce, beforeThawRequestList.nonce + 1); + if (beforeThawRequestList.count != 0) { + assertEq(afterPreviousTailThawRequest.next, thawRequestId); + } + + return thawRequestId; + } + + function _deprovision(address serviceProvider, address verifier, uint256 nThawRequests) internal { + // before + Provision memory beforeProvision = staking.getProvision(serviceProvider, verifier); + ServiceProviderInternal memory beforeServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + LinkedList.List memory beforeThawRequestList = staking.getThawRequestList( + serviceProvider, + verifier, + serviceProvider + ); + + CalcValues_ThawRequestData memory calcValues = calcThawRequestData(serviceProvider, verifier, serviceProvider, nThawRequests, false); + + // deprovision + for (uint i = 0; i < calcValues.thawRequestsFulfilledList.length; i++) { + ThawRequest memory thawRequest = calcValues.thawRequestsFulfilledList[i]; + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawRequestFulfilled( + calcValues.thawRequestsFulfilledListIds[i], + calcValues.thawRequestsFulfilledListTokens[i], + thawRequest.shares, + thawRequest.thawingUntil + ); + } + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawRequestsFulfilled( + serviceProvider, + verifier, + serviceProvider, + calcValues.thawRequestsFulfilledList.length, + calcValues.tokensThawed + ); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.TokensDeprovisioned(serviceProvider, verifier, calcValues.tokensThawed); + staking.deprovision(serviceProvider, verifier, nThawRequests); + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + LinkedList.List memory afterThawRequestList = staking.getThawRequestList( + serviceProvider, + verifier, + serviceProvider + ); + + // assert + assertEq(afterProvision.tokens, beforeProvision.tokens - calcValues.tokensThawed); + assertEq(afterProvision.tokensThawing, calcValues.tokensThawing); + assertEq(afterProvision.sharesThawing, calcValues.sharesThawing); + assertEq(afterProvision.maxVerifierCut, beforeProvision.maxVerifierCut); + assertEq(afterProvision.thawingPeriod, beforeProvision.thawingPeriod); + assertEq(afterProvision.createdAt, beforeProvision.createdAt); + assertEq(afterProvision.maxVerifierCutPending, beforeProvision.maxVerifierCutPending); + assertEq(afterProvision.thawingPeriodPending, beforeProvision.thawingPeriodPending); + assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked); + assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned - calcValues.tokensThawed); + assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); + assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeServiceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLockedUntil, + beforeServiceProvider.__DEPRECATED_tokensLockedUntil + ); + for (uint i = 0; i < calcValues.thawRequestsFulfilledListIds.length; i++) { + ThawRequest memory thawRequest = staking.getThawRequest(calcValues.thawRequestsFulfilledListIds[i]); + assertEq(thawRequest.shares, 0); + assertEq(thawRequest.thawingUntil, 0); + assertEq(thawRequest.next, bytes32(0)); + } + if (calcValues.thawRequestsFulfilledList.length == 0) { + assertEq(afterThawRequestList.head, beforeThawRequestList.head); + } else { + assertEq( + afterThawRequestList.head, + calcValues.thawRequestsFulfilledList.length == beforeThawRequestList.count + ? bytes32(0) + : calcValues.thawRequestsFulfilledList[calcValues.thawRequestsFulfilledList.length - 1].next + ); + } + assertEq( + afterThawRequestList.tail, + calcValues.thawRequestsFulfilledList.length == beforeThawRequestList.count + ? bytes32(0) + : beforeThawRequestList.tail + ); + assertEq(afterThawRequestList.count, beforeThawRequestList.count - calcValues.thawRequestsFulfilledList.length); + assertEq(afterThawRequestList.nonce, beforeThawRequestList.nonce); + } + + struct BeforeValues_Reprovision { + Provision provision; + Provision provisionNewVerifier; + ServiceProviderInternal serviceProvider; + LinkedList.List thawRequestList; + } + function _reprovision( + address serviceProvider, + address verifier, + address newVerifier, + uint256 tokens, + uint256 nThawRequests + ) internal { + // before + BeforeValues_Reprovision memory beforeValues = BeforeValues_Reprovision({ + provision: staking.getProvision(serviceProvider, verifier), + provisionNewVerifier: staking.getProvision(serviceProvider, newVerifier), + serviceProvider: _getStorage_ServiceProviderInternal(serviceProvider), + thawRequestList: staking.getThawRequestList(serviceProvider, verifier, serviceProvider) + }); + + // calc + CalcValues_ThawRequestData memory calcValues = calcThawRequestData(serviceProvider, verifier, serviceProvider, nThawRequests, false); + + // reprovision + for (uint i = 0; i < calcValues.thawRequestsFulfilledList.length; i++) { + ThawRequest memory thawRequest = calcValues.thawRequestsFulfilledList[i]; + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawRequestFulfilled( + calcValues.thawRequestsFulfilledListIds[i], + calcValues.thawRequestsFulfilledListTokens[i], + thawRequest.shares, + thawRequest.thawingUntil + ); + } + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawRequestsFulfilled( + serviceProvider, + verifier, + serviceProvider, + calcValues.thawRequestsFulfilledList.length, + calcValues.tokensThawed + ); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.TokensDeprovisioned(serviceProvider, verifier, calcValues.tokensThawed); + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionIncreased(serviceProvider, newVerifier, tokens); + staking.reprovision(serviceProvider, verifier, newVerifier, tokens, nThawRequests); + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); + Provision memory afterProvisionNewVerifier = staking.getProvision(serviceProvider, newVerifier); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + LinkedList.List memory afterThawRequestList = staking.getThawRequestList( + serviceProvider, + verifier, + serviceProvider + ); + + // assert: provision old verifier + assertEq(afterProvision.tokens, beforeValues.provision.tokens - calcValues.tokensThawed); + assertEq(afterProvision.tokensThawing, calcValues.tokensThawing); + assertEq(afterProvision.sharesThawing, calcValues.sharesThawing); + assertEq(afterProvision.maxVerifierCut, beforeValues.provision.maxVerifierCut); + assertEq(afterProvision.thawingPeriod, beforeValues.provision.thawingPeriod); + assertEq(afterProvision.createdAt, beforeValues.provision.createdAt); + assertEq(afterProvision.maxVerifierCutPending, beforeValues.provision.maxVerifierCutPending); + assertEq(afterProvision.thawingPeriodPending, beforeValues.provision.thawingPeriodPending); + + // assert: provision new verifier + assertEq(afterProvisionNewVerifier.tokens, beforeValues.provisionNewVerifier.tokens + tokens); + assertEq(afterProvisionNewVerifier.tokensThawing, beforeValues.provisionNewVerifier.tokensThawing); + assertEq(afterProvisionNewVerifier.sharesThawing, beforeValues.provisionNewVerifier.sharesThawing); + assertEq(afterProvisionNewVerifier.maxVerifierCut, beforeValues.provisionNewVerifier.maxVerifierCut); + assertEq(afterProvisionNewVerifier.thawingPeriod, beforeValues.provisionNewVerifier.thawingPeriod); + assertEq(afterProvisionNewVerifier.createdAt, beforeValues.provisionNewVerifier.createdAt); + assertEq(afterProvisionNewVerifier.maxVerifierCutPending, beforeValues.provisionNewVerifier.maxVerifierCutPending); + assertEq(afterProvisionNewVerifier.thawingPeriodPending, beforeValues.provisionNewVerifier.thawingPeriodPending); + + // assert: service provider + assertEq(afterServiceProvider.tokensStaked, beforeValues.serviceProvider.tokensStaked); + assertEq( + afterServiceProvider.tokensProvisioned, + beforeValues.serviceProvider.tokensProvisioned + tokens - calcValues.tokensThawed + ); + assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeValues.serviceProvider.__DEPRECATED_tokensAllocated); + assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeValues.serviceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLockedUntil, + beforeValues.serviceProvider.__DEPRECATED_tokensLockedUntil + ); + + // assert: thaw request list old verifier + for (uint i = 0; i < calcValues.thawRequestsFulfilledListIds.length; i++) { + ThawRequest memory thawRequest = staking.getThawRequest(calcValues.thawRequestsFulfilledListIds[i]); + assertEq(thawRequest.shares, 0); + assertEq(thawRequest.thawingUntil, 0); + assertEq(thawRequest.next, bytes32(0)); + } + if (calcValues.thawRequestsFulfilledList.length == 0) { + assertEq(afterThawRequestList.head, beforeValues.thawRequestList.head); + } else { + assertEq( + afterThawRequestList.head, + calcValues.thawRequestsFulfilledList.length == beforeValues.thawRequestList.count + ? bytes32(0) + : calcValues.thawRequestsFulfilledList[calcValues.thawRequestsFulfilledList.length - 1].next + ); + } + assertEq( + afterThawRequestList.tail, + calcValues.thawRequestsFulfilledList.length == beforeValues.thawRequestList.count + ? bytes32(0) + : beforeValues.thawRequestList.tail + ); + assertEq(afterThawRequestList.count, beforeValues.thawRequestList.count - calcValues.thawRequestsFulfilledList.length); + assertEq(afterThawRequestList.nonce, beforeValues.thawRequestList.nonce); + } + + function _setProvisionParameters( + address serviceProvider, + address verifier, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) internal { + // before + Provision memory beforeProvision = staking.getProvision(serviceProvider, verifier); + + // setProvisionParameters + if (beforeProvision.maxVerifierCut != maxVerifierCut || beforeProvision.thawingPeriod != thawingPeriod) { + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersStaged( + serviceProvider, + verifier, + maxVerifierCut, + thawingPeriod + ); + } + staking.setProvisionParameters(serviceProvider, verifier, maxVerifierCut, thawingPeriod); + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); + + // assert + assertEq(afterProvision.tokens, beforeProvision.tokens); + assertEq(afterProvision.tokensThawing, beforeProvision.tokensThawing); + assertEq(afterProvision.sharesThawing, beforeProvision.sharesThawing); + assertEq(afterProvision.maxVerifierCut, beforeProvision.maxVerifierCut); + assertEq(afterProvision.thawingPeriod, beforeProvision.thawingPeriod); + assertEq(afterProvision.createdAt, beforeProvision.createdAt); + assertEq(afterProvision.maxVerifierCutPending, maxVerifierCut); + assertEq(afterProvision.thawingPeriodPending, thawingPeriod); + } + + function _acceptProvisionParameters(address serviceProvider) internal { + (, address msgSender, ) = vm.readCallers(); + + // before + Provision memory beforeProvision = staking.getProvision(serviceProvider, msgSender); + + // acceptProvisionParameters + if ( + beforeProvision.maxVerifierCutPending != beforeProvision.maxVerifierCut || + beforeProvision.thawingPeriodPending != beforeProvision.thawingPeriod + ) { + vm.expectEmit(); + emit IHorizonStakingMain.ProvisionParametersSet( + serviceProvider, + msgSender, + beforeProvision.maxVerifierCutPending, + beforeProvision.thawingPeriodPending + ); + } + staking.acceptProvisionParameters(serviceProvider); + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, msgSender); + + // assert + assertEq(afterProvision.tokens, beforeProvision.tokens); + assertEq(afterProvision.tokensThawing, beforeProvision.tokensThawing); + assertEq(afterProvision.sharesThawing, beforeProvision.sharesThawing); + assertEq(afterProvision.maxVerifierCut, beforeProvision.maxVerifierCutPending); + assertEq(afterProvision.maxVerifierCut, afterProvision.maxVerifierCutPending); + assertEq(afterProvision.thawingPeriod, beforeProvision.thawingPeriodPending); + assertEq(afterProvision.thawingPeriod, afterProvision.thawingPeriodPending); + assertEq(afterProvision.createdAt, beforeProvision.createdAt); + } + + function _setOperator(address operator, address verifier, bool allow) internal { + __setOperator(operator, verifier, allow, false); + } + + function _setOperatorLocked(address operator, address verifier, bool allow) internal { + __setOperator(operator, verifier, allow, true); + } + + function __setOperator(address operator, address verifier, bool allow, bool locked) private { + (, address msgSender, ) = vm.readCallers(); + + // staking contract knows the address of the legacy subgraph service + // but we cannot read it as it's an immutable, we have to use the global var :/ + bool legacy = verifier == subgraphDataServiceLegacyAddress; + + // before + bool beforeOperatorAllowed = _getStorage_OperatorAuth(msgSender, operator, verifier, legacy); + bool beforeOperatorAllowedGetter = staking.isAuthorized(operator, msgSender, verifier); + assertEq(beforeOperatorAllowed, beforeOperatorAllowedGetter); + + // setOperator + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.OperatorSet(msgSender, operator, verifier, allow); + if (locked) { + staking.setOperatorLocked(operator, verifier, allow); + } else { + staking.setOperator(operator, verifier, allow); + } + + // after + bool afterOperatorAllowed = _getStorage_OperatorAuth(msgSender, operator, verifier, legacy); + bool afterOperatorAllowedGetter = staking.isAuthorized(operator, msgSender, verifier); + assertEq(afterOperatorAllowed, afterOperatorAllowedGetter); + + // assert + assertEq(afterOperatorAllowed, allow); + } + + function _delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) internal { + __delegate(serviceProvider, verifier, tokens, minSharesOut, false); + } + + function _delegate(address serviceProvider, uint256 tokens) internal { + __delegate(serviceProvider, subgraphDataServiceLegacyAddress, tokens, 0, true); + } + + function __delegate( + address serviceProvider, + address verifier, + uint256 tokens, + uint256 minSharesOut, + bool legacy + ) private { + (, address delegator, ) = vm.readCallers(); + + // before + DelegationPoolInternalTest memory beforePool = _getStorage_DelegationPoolInternal( + serviceProvider, + verifier, + legacy + ); + DelegationInternal memory beforeDelegation = _getStorage_Delegation( + serviceProvider, + verifier, + delegator, + legacy + ); + uint256 beforeDelegatorBalance = token.balanceOf(delegator); + uint256 beforeStakingBalance = token.balanceOf(address(staking)); + + uint256 calcShares = (beforePool.tokens == 0 || beforePool.tokens == beforePool.tokensThawing) + ? tokens + : ((tokens * beforePool.shares) / (beforePool.tokens - beforePool.tokensThawing)); + + // delegate token.approve(address(staking), tokens); - staking.stakeTo(users.indexer, tokens); - staking.provision(users.indexer, dataServiceAddress, tokens, maxVerifierCut, thawingPeriod); + vm.expectEmit(); + emit IHorizonStakingMain.TokensDelegated(serviceProvider, verifier, delegator, tokens); + if (legacy) { + staking.delegate(serviceProvider, tokens); + } else { + staking.delegate(serviceProvider, verifier, tokens, minSharesOut); + } + + // after + DelegationPoolInternalTest memory afterPool = _getStorage_DelegationPoolInternal( + serviceProvider, + verifier, + legacy + ); + DelegationInternal memory afterDelegation = _getStorage_Delegation( + serviceProvider, + verifier, + delegator, + legacy + ); + uint256 afterDelegatorBalance = token.balanceOf(delegator); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + + uint256 deltaShares = afterDelegation.shares - beforeDelegation.shares; + + // assertions + assertEq(beforePool.tokens + tokens, afterPool.tokens); + assertEq(beforePool.shares + calcShares, afterPool.shares); + assertEq(beforePool.tokensThawing, afterPool.tokensThawing); + assertEq(beforePool.sharesThawing, afterPool.sharesThawing); + assertEq(beforeDelegation.shares + calcShares, afterDelegation.shares); + assertEq(beforeDelegation.__DEPRECATED_tokensLocked, afterDelegation.__DEPRECATED_tokensLocked); + assertEq(beforeDelegation.__DEPRECATED_tokensLockedUntil, afterDelegation.__DEPRECATED_tokensLockedUntil); + assertGe(deltaShares, minSharesOut); + assertEq(calcShares, deltaShares); + assertEq(beforeDelegatorBalance - tokens, afterDelegatorBalance); + assertEq(beforeStakingBalance + tokens, afterStakingBalance); + } + + function _undelegate(address serviceProvider, address verifier, uint256 shares) internal { + __undelegate(serviceProvider, verifier, shares, false); + } + + function _undelegate(address serviceProvider, uint256 shares) internal { + __undelegate(serviceProvider, subgraphDataServiceLegacyAddress, shares, true); + } + + struct BeforeValues_Undelegate { + DelegationPoolInternalTest pool; + DelegationInternal delegation; + LinkedList.List thawRequestList; + uint256 delegatedTokens; + } + struct CalcValues_Undelegate { + uint256 tokens; + uint256 thawingShares; + uint64 thawingUntil; + bytes32 thawRequestId; + } + + function __undelegate(address serviceProvider, address verifier, uint256 shares, bool legacy) private { + (, address delegator, ) = vm.readCallers(); + + // before + BeforeValues_Undelegate memory beforeValues; + beforeValues.pool = _getStorage_DelegationPoolInternal(serviceProvider, verifier, legacy); + beforeValues.delegation = _getStorage_Delegation(serviceProvider, verifier, delegator, legacy); + beforeValues.thawRequestList = staking.getThawRequestList(serviceProvider, verifier, delegator); + beforeValues.delegatedTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); + + // calc + CalcValues_Undelegate memory calcValues; + calcValues.tokens = ((beforeValues.pool.tokens - beforeValues.pool.tokensThawing) * shares) / beforeValues.pool.shares; + calcValues.thawingShares = beforeValues.pool.tokensThawing == 0 + ? calcValues.tokens + : (beforeValues.pool.sharesThawing * calcValues.tokens) / beforeValues.pool.tokensThawing; + calcValues.thawingUntil = + staking.getProvision(serviceProvider, verifier).thawingPeriod + + uint64(block.timestamp); + calcValues.thawRequestId = keccak256( + abi.encodePacked(serviceProvider, verifier, delegator, beforeValues.thawRequestList.nonce) + ); + + // undelegate + vm.expectEmit(); + emit IHorizonStakingMain.ThawRequestCreated( + serviceProvider, + verifier, + delegator, + calcValues.thawingShares, + calcValues.thawingUntil, + calcValues.thawRequestId + ); + vm.expectEmit(); + emit IHorizonStakingMain.TokensUndelegated(serviceProvider, verifier, delegator, calcValues.tokens); + if (legacy) { + staking.undelegate(serviceProvider, shares); + } else { + staking.undelegate(serviceProvider, verifier, shares); + } + + // after + DelegationPoolInternalTest memory afterPool = _getStorage_DelegationPoolInternal( + users.indexer, + verifier, + legacy + ); + DelegationInternal memory afterDelegation = _getStorage_Delegation( + serviceProvider, + verifier, + delegator, + legacy + ); + LinkedList.List memory afterThawRequestList = staking.getThawRequestList(serviceProvider, verifier, delegator); + ThawRequest memory afterThawRequest = staking.getThawRequest(calcValues.thawRequestId); + uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); + + // assertions + assertEq(beforeValues.pool.shares, afterPool.shares + shares); + assertEq(beforeValues.pool.tokens, afterPool.tokens); + assertEq(beforeValues.pool.tokensThawing + calcValues.tokens, afterPool.tokensThawing); + assertEq(beforeValues.pool.sharesThawing + calcValues.thawingShares, afterPool.sharesThawing); + assertEq(beforeValues.delegation.shares - shares, afterDelegation.shares); + assertEq(afterThawRequest.shares, calcValues.thawingShares); + assertEq(afterThawRequest.thawingUntil, calcValues.thawingUntil); + assertEq(afterThawRequest.next, bytes32(0)); + assertEq(calcValues.thawRequestId, afterThawRequestList.tail); + assertEq(beforeValues.thawRequestList.nonce + 1, afterThawRequestList.nonce); + assertEq(beforeValues.thawRequestList.count + 1, afterThawRequestList.count); + assertEq(afterDelegatedTokens + calcValues.tokens, beforeValues.delegatedTokens); + } + + function _withdrawDelegated( + address serviceProvider, + address verifier, + address newServiceProvider, + uint256 minSharesForNewProvider, + uint256 nThawRequests + ) internal { + __withdrawDelegated( + serviceProvider, + verifier, + newServiceProvider, + minSharesForNewProvider, + nThawRequests, + false + ); + } + + function _withdrawDelegated(address serviceProvider, address newServiceProvider) internal { + __withdrawDelegated(serviceProvider, subgraphDataServiceLegacyAddress, newServiceProvider, 0, 0, true); + } + + struct BeforeValues_WithdrawDelegated { + DelegationPoolInternalTest pool; + DelegationPoolInternalTest newPool; + DelegationInternal newDelegation; + LinkedList.List thawRequestList; + uint256 senderBalance; + uint256 stakingBalance; + } + struct AfterValues_WithdrawDelegated { + DelegationPoolInternalTest pool; + DelegationPoolInternalTest newPool; + DelegationInternal newDelegation; + LinkedList.List thawRequestList; + uint256 senderBalance; + uint256 stakingBalance; + } + function __withdrawDelegated( + address _serviceProvider, + address _verifier, + address _newServiceProvider, + uint256 _minSharesForNewProvider, + uint256 _nThawRequests, + bool legacy + ) private { + (, address msgSender, ) = vm.readCallers(); + + bool reDelegate = _newServiceProvider != address(0); + + // before + BeforeValues_WithdrawDelegated memory beforeValues; + beforeValues.pool = _getStorage_DelegationPoolInternal(_serviceProvider, _verifier, legacy); + beforeValues.newPool = _getStorage_DelegationPoolInternal(_newServiceProvider, _verifier, legacy); + beforeValues.newDelegation = _getStorage_Delegation(_serviceProvider, _verifier, msgSender, legacy); + beforeValues.thawRequestList = staking.getThawRequestList(_serviceProvider, _verifier, msgSender); + beforeValues.senderBalance = token.balanceOf(msgSender); + beforeValues.stakingBalance = token.balanceOf(address(staking)); + + CalcValues_ThawRequestData memory calcValues = calcThawRequestData( + _serviceProvider, + _verifier, + msgSender, + _nThawRequests, + true + ); + + // withdrawDelegated + for (uint i = 0; i < calcValues.thawRequestsFulfilledList.length; i++) { + ThawRequest memory thawRequest = calcValues.thawRequestsFulfilledList[i]; + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawRequestFulfilled( + calcValues.thawRequestsFulfilledListIds[i], + calcValues.thawRequestsFulfilledListTokens[i], + thawRequest.shares, + thawRequest.thawingUntil + ); + } + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawRequestsFulfilled( + _serviceProvider, + _verifier, + msgSender, + calcValues.thawRequestsFulfilledList.length, + calcValues.tokensThawed + ); + if (calcValues.tokensThawed != 0) { + vm.expectEmit(); + if (reDelegate) { + emit IHorizonStakingMain.TokensDelegated(_newServiceProvider, _verifier, msgSender, calcValues.tokensThawed); + } else { + emit Transfer(address(staking), msgSender, calcValues.tokensThawed); + } + } + vm.expectEmit(); + emit IHorizonStakingMain.DelegatedTokensWithdrawn(_serviceProvider, _verifier, msgSender, calcValues.tokensThawed); + staking.withdrawDelegated( + _serviceProvider, + _verifier, + _newServiceProvider, + _minSharesForNewProvider, + _nThawRequests + ); + + // after + AfterValues_WithdrawDelegated memory afterValues; + afterValues.pool = _getStorage_DelegationPoolInternal(_serviceProvider, _verifier, legacy); + afterValues.newPool = _getStorage_DelegationPoolInternal(_newServiceProvider, _verifier, legacy); + afterValues.newDelegation = _getStorage_Delegation(_newServiceProvider, _verifier, msgSender, legacy); + afterValues.thawRequestList = staking.getThawRequestList(_serviceProvider, _verifier, msgSender); + afterValues.senderBalance = token.balanceOf(msgSender); + afterValues.stakingBalance = token.balanceOf(address(staking)); + + // assert + assertEq(afterValues.pool.tokens, beforeValues.pool.tokens - calcValues.tokensThawed); + assertEq(afterValues.pool.shares, beforeValues.pool.shares); + assertEq(afterValues.pool.tokensThawing, calcValues.tokensThawing); + assertEq(afterValues.pool.sharesThawing, calcValues.sharesThawing); + + for (uint i = 0; i < calcValues.thawRequestsFulfilledListIds.length; i++) { + ThawRequest memory thawRequest = staking.getThawRequest(calcValues.thawRequestsFulfilledListIds[i]); + assertEq(thawRequest.shares, 0); + assertEq(thawRequest.thawingUntil, 0); + assertEq(thawRequest.next, bytes32(0)); + } + if (calcValues.thawRequestsFulfilledList.length == 0) { + assertEq(afterValues.thawRequestList.head, beforeValues.thawRequestList.head); + } else { + assertEq( + afterValues.thawRequestList.head, + calcValues.thawRequestsFulfilledList.length == beforeValues.thawRequestList.count + ? bytes32(0) + : calcValues.thawRequestsFulfilledList[calcValues.thawRequestsFulfilledList.length - 1].next + ); + } + assertEq( + afterValues.thawRequestList.tail, + calcValues.thawRequestsFulfilledList.length == beforeValues.thawRequestList.count + ? bytes32(0) + : beforeValues.thawRequestList.tail + ); + assertEq(afterValues.thawRequestList.count, beforeValues.thawRequestList.count - calcValues.thawRequestsFulfilledList.length); + assertEq(afterValues.thawRequestList.nonce, beforeValues.thawRequestList.nonce); + + if (reDelegate) { + uint256 calcShares = (afterValues.newPool.tokens == 0 || + afterValues.newPool.tokens == afterValues.newPool.tokensThawing) + ? calcValues.tokensThawed + : ((calcValues.tokensThawed * afterValues.newPool.shares) / + (afterValues.newPool.tokens - afterValues.newPool.tokensThawing)); + uint256 deltaShares = afterValues.newDelegation.shares - beforeValues.newDelegation.shares; + + assertEq(afterValues.newPool.tokens, beforeValues.newPool.tokens + calcValues.tokensThawed); + assertEq(afterValues.newPool.shares, beforeValues.newPool.shares + calcShares); + assertEq(afterValues.newPool.tokensThawing, beforeValues.newPool.tokensThawing); + assertEq(afterValues.newPool.sharesThawing, beforeValues.newPool.sharesThawing); + assertEq(afterValues.newDelegation.shares, beforeValues.newDelegation.shares + calcShares); + assertEq(afterValues.newDelegation.__DEPRECATED_tokensLocked, beforeValues.newDelegation.__DEPRECATED_tokensLocked); + assertEq( + afterValues.newDelegation.__DEPRECATED_tokensLockedUntil, + beforeValues.newDelegation.__DEPRECATED_tokensLockedUntil + ); + assertGe(deltaShares, _minSharesForNewProvider); + assertEq(calcShares, deltaShares); + assertEq(afterValues.senderBalance - beforeValues.senderBalance, 0); + assertEq(beforeValues.stakingBalance - afterValues.stakingBalance, 0); + } else { + assertEq(beforeValues.stakingBalance - afterValues.stakingBalance, calcValues.tokensThawed); + assertEq(afterValues.senderBalance - beforeValues.senderBalance, calcValues.tokensThawed); + } + } + + function _addToDelegationPool(address serviceProvider, address verifier, uint256 tokens) internal { + (, address msgSender, ) = vm.readCallers(); + + // staking contract knows the address of the legacy subgraph service + // but we cannot read it as it's an immutable, we have to use the global var :/ + bool legacy = verifier == subgraphDataServiceLegacyAddress; + + // before + DelegationPoolInternalTest memory beforePool = _getStorage_DelegationPoolInternal( + serviceProvider, + verifier, + legacy + ); + uint256 beforeSenderBalance = token.balanceOf(msgSender); + uint256 beforeStakingBalance = token.balanceOf(address(staking)); + + // addToDelegationPool + vm.expectEmit(); + emit Transfer(msgSender, address(staking), tokens); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.TokensToDelegationPoolAdded(serviceProvider, verifier, tokens); + staking.addToDelegationPool(serviceProvider, verifier, tokens); + + // after + DelegationPoolInternalTest memory afterPool = _getStorage_DelegationPoolInternal( + serviceProvider, + verifier, + legacy + ); + uint256 afterSenderBalance = token.balanceOf(msgSender); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + + // assert + assertEq(beforeSenderBalance - tokens, afterSenderBalance); + assertEq(beforeStakingBalance + tokens, afterStakingBalance); + assertEq(beforePool.tokens + tokens, afterPool.tokens); + assertEq(beforePool.shares, afterPool.shares); + assertEq(beforePool.tokensThawing, afterPool.tokensThawing); + assertEq(beforePool.sharesThawing, afterPool.sharesThawing); } - function _setDelegationFeeCut(IGraphPayments.PaymentTypes paymentType, uint256 cut) internal { - staking.setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, cut); - uint256 delegationFeeCut = staking.getDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType); - assertEq(delegationFeeCut, cut); + function _setDelegationFeeCut( + address serviceProvider, + address verifier, + IGraphPayments.PaymentTypes paymentType, + uint256 feeCut + ) internal { + // setDelegationFeeCut + vm.expectEmit(); + emit IHorizonStakingMain.DelegationFeeCutSet(serviceProvider, verifier, paymentType, feeCut); + staking.setDelegationFeeCut(serviceProvider, verifier, paymentType, feeCut); + + // after + uint256 afterDelegationFeeCut = staking.getDelegationFeeCut(serviceProvider, verifier, paymentType); + + // assert + assertEq(afterDelegationFeeCut, feeCut); + } + + function _setAllowedLockedVerifier(address verifier, bool allowed) internal { + // setAllowedLockedVerifier + vm.expectEmit(); + emit IHorizonStakingMain.AllowedLockedVerifierSet(verifier, allowed); + staking.setAllowedLockedVerifier(verifier, allowed); + + // after + bool afterAllowed = staking.isAllowedLockedVerifier(verifier); + + // assert + assertEq(afterAllowed, allowed); + } + + function _setDelegationSlashingEnabled() internal { + // setDelegationSlashingEnabled + vm.expectEmit(); + emit IHorizonStakingMain.DelegationSlashingEnabled(true); + staking.setDelegationSlashingEnabled(); + + // after + bool afterEnabled = staking.isDelegationSlashingEnabled(); + + // assert + assertEq(afterEnabled, true); + } + + function _clearThawingPeriod() internal { + // clearThawingPeriod + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ThawingPeriodCleared(); + staking.clearThawingPeriod(); + + // after + uint64 afterThawingPeriod = staking.__DEPRECATED_getThawingPeriod(); + + // assert + assertEq(afterThawingPeriod, 0); + } + + function _setMaxThawingPeriod(uint64 maxThawingPeriod) internal { + // setMaxThawingPeriod + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.MaxThawingPeriodSet(maxThawingPeriod); + staking.setMaxThawingPeriod(maxThawingPeriod); + + // after + uint64 afterMaxThawingPeriod = staking.getMaxThawingPeriod(); + + // assert + assertEq(afterMaxThawingPeriod, maxThawingPeriod); + } + + function _setCounterpartStakingAddress(address counterpartStakingAddress) internal { + // setCounterpartStakingAddress + vm.expectEmit(address(staking)); + emit IHorizonStakingExtension.CounterpartStakingAddressSet(counterpartStakingAddress); + staking.setCounterpartStakingAddress(counterpartStakingAddress); + + // after + address afterCounterpartStakingAddress = _getStorage_CounterpartStakingAddress(); + + // assert + assertEq(afterCounterpartStakingAddress, counterpartStakingAddress); + } + + struct BeforeValues_ReceiveDelegation { + DelegationPoolInternalTest pool; + DelegationInternal delegation; + uint256 delegatedTokens; + uint256 stakingBalance; + uint256 delegatorBalance; + } + function _onTokenTransfer_ReceiveDelegation(address from, uint256 tokens, bytes memory data) internal { + address serviceProvider; + address delegator; + { + (, bytes memory fnData) = abi.decode(data, (uint8, bytes)); + (serviceProvider, delegator) = abi.decode(fnData, (address, address)); + } + + // before + BeforeValues_ReceiveDelegation memory beforeValues; + beforeValues.pool = _getStorage_DelegationPoolInternal(serviceProvider, subgraphDataServiceLegacyAddress, true); + beforeValues.delegation = _getStorage_Delegation( + serviceProvider, + subgraphDataServiceLegacyAddress, + delegator, + true + ); + beforeValues.stakingBalance = token.balanceOf(address(staking)); + beforeValues.delegatorBalance = token.balanceOf(delegator); + beforeValues.delegatedTokens = staking.getDelegatedTokensAvailable( + serviceProvider, + subgraphDataServiceLegacyAddress + ); + + // calc + uint256 calcShares = (beforeValues.pool.tokens == 0 || beforeValues.pool.tokens == beforeValues.pool.tokensThawing) + ? tokens + : ((tokens * beforeValues.pool.shares) / (beforeValues.pool.tokens - beforeValues.pool.tokensThawing)); + + bool earlyExit = (calcShares == 0 || tokens < 1 ether) || + (beforeValues.pool.tokens == 0 && (beforeValues.pool.shares != 0 || beforeValues.pool.sharesThawing != 0)); + + // onTokenTransfer + if (earlyExit) { + vm.expectEmit(); + emit Transfer(address(staking), delegator, tokens); + vm.expectEmit(); + emit IL2StakingBase.TransferredDelegationReturnedToDelegator(serviceProvider, delegator, tokens); + } else { + vm.expectEmit(); + emit IHorizonStakingExtension.StakeDelegated(serviceProvider, delegator, tokens, calcShares); + } + staking.onTokenTransfer(from, tokens, data); + + // after + DelegationPoolInternalTest memory afterPool = _getStorage_DelegationPoolInternal(serviceProvider, subgraphDataServiceLegacyAddress, true); + DelegationInternal memory afterDelegation = _getStorage_Delegation( + serviceProvider, + subgraphDataServiceLegacyAddress, + delegator, + true + ); + uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable( + serviceProvider, + subgraphDataServiceLegacyAddress + ); + uint256 afterDelegatorBalance = token.balanceOf(delegator); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + + // assertions + if (earlyExit) { + assertEq(beforeValues.pool.tokens, afterPool.tokens); + assertEq(beforeValues.pool.shares, afterPool.shares); + assertEq(beforeValues.pool.tokensThawing, afterPool.tokensThawing); + assertEq(beforeValues.pool.sharesThawing, afterPool.sharesThawing); + assertEq(0, afterDelegation.shares - beforeValues.delegation.shares); + assertEq(beforeValues.delegatedTokens, afterDelegatedTokens); + assertEq(beforeValues.delegatorBalance + tokens, afterDelegatorBalance); + assertEq(beforeValues.stakingBalance - tokens, afterStakingBalance); + } else { + assertEq(beforeValues.pool.tokens + tokens, afterPool.tokens); + assertEq(beforeValues.pool.shares + calcShares, afterPool.shares); + assertEq(beforeValues.pool.tokensThawing, afterPool.tokensThawing); + assertEq(beforeValues.pool.sharesThawing, afterPool.sharesThawing); + assertEq(calcShares, afterDelegation.shares - beforeValues.delegation.shares); + assertEq(beforeValues.delegatedTokens + tokens, afterDelegatedTokens); + assertEq(beforeValues.delegatorBalance, afterDelegatorBalance); + assertEq(beforeValues.stakingBalance, afterStakingBalance); + } + } + + struct BeforeValues_Slash { + Provision provision; + DelegationPoolInternalTest pool; + ServiceProviderInternal serviceProvider; + uint256 stakingBalance; + uint256 verifierBalance; + } + struct CalcValues_Slash { + uint256 tokensToSlash; + uint256 providerTokensSlashed; + uint256 delegationTokensSlashed; + } + + function _slash(address serviceProvider, address verifier, uint256 tokens, uint256 verifierCutAmount) internal { + bool isDelegationSlashingEnabled = staking.isDelegationSlashingEnabled(); + + // staking contract knows the address of the legacy subgraph service + // but we cannot read it as it's an immutable, we have to use the global var :/ + bool legacy = verifier == subgraphDataServiceLegacyAddress; + + // before + BeforeValues_Slash memory before; + before.provision = staking.getProvision(serviceProvider, verifier); + before.pool = _getStorage_DelegationPoolInternal(serviceProvider, verifier, legacy); + before.serviceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + before.stakingBalance = token.balanceOf(address(staking)); + before.verifierBalance = token.balanceOf(verifier); + + // Calculate expected tokens after slashing + CalcValues_Slash memory calcValues; + calcValues.tokensToSlash = MathUtils.min(tokens, before.provision.tokens + before.pool.tokens); + calcValues.providerTokensSlashed = MathUtils.min(before.provision.tokens, calcValues.tokensToSlash); + calcValues.delegationTokensSlashed = calcValues.tokensToSlash - calcValues.providerTokensSlashed; + + if (calcValues.tokensToSlash > 0) { + if (verifierCutAmount > 0) { + vm.expectEmit(address(token)); + emit Transfer(address(staking), verifier, verifierCutAmount); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.VerifierTokensSent(serviceProvider, verifier, verifier, verifierCutAmount); + } + if (calcValues.providerTokensSlashed - verifierCutAmount > 0) { + vm.expectEmit(address(token)); + emit Transfer(address(staking), address(0), calcValues.providerTokensSlashed - verifierCutAmount); + } + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.ProvisionSlashed(serviceProvider, verifier, calcValues.providerTokensSlashed); + } + + if (calcValues.delegationTokensSlashed > 0) { + if (isDelegationSlashingEnabled) { + vm.expectEmit(address(token)); + emit Transfer(address(staking), address(0), calcValues.delegationTokensSlashed); + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.DelegationSlashed( + serviceProvider, + verifier, + calcValues.delegationTokensSlashed + ); + } else { + vm.expectEmit(address(staking)); + emit IHorizonStakingMain.DelegationSlashingSkipped( + serviceProvider, + verifier, + calcValues.delegationTokensSlashed + ); + } + } + staking.slash(serviceProvider, tokens, verifierCutAmount, verifier); + + // after + Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); + DelegationPoolInternalTest memory afterPool = _getStorage_DelegationPoolInternal( + serviceProvider, + verifier, + legacy + ); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal(serviceProvider); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + uint256 afterVerifierBalance = token.balanceOf(verifier); + + { + uint256 tokensSlashed = calcValues.providerTokensSlashed + + (isDelegationSlashingEnabled ? calcValues.delegationTokensSlashed : 0); + uint256 provisionThawingTokens = (before.provision.tokensThawing * + (1e18 - ((calcValues.providerTokensSlashed * 1e18) / before.provision.tokens))) / (1e18); + + // assert + assertEq(afterProvision.tokens + calcValues.providerTokensSlashed, before.provision.tokens); + assertEq(afterProvision.tokensThawing, provisionThawingTokens); + assertEq(afterProvision.sharesThawing, before.provision.sharesThawing); + assertEq(afterProvision.maxVerifierCut, before.provision.maxVerifierCut); + assertEq(afterProvision.maxVerifierCutPending, before.provision.maxVerifierCutPending); + assertEq(afterProvision.thawingPeriod, before.provision.thawingPeriod); + assertEq(afterProvision.thawingPeriodPending, before.provision.thawingPeriodPending); + + if (isDelegationSlashingEnabled) { + uint256 poolThawingTokens = (before.pool.tokensThawing * + (1e18 - ((calcValues.delegationTokensSlashed * 1e18) / before.pool.tokens))) / (1e18); + assertEq(afterPool.tokens + calcValues.delegationTokensSlashed, before.pool.tokens); + assertEq(afterPool.shares, before.pool.shares); + assertEq(afterPool.tokensThawing, poolThawingTokens); + assertEq(afterPool.sharesThawing, before.pool.sharesThawing); + } + + assertEq(before.stakingBalance - tokensSlashed, afterStakingBalance); + assertEq(before.verifierBalance + verifierCutAmount, afterVerifierBalance); + + assertEq( + afterServiceProvider.tokensStaked + calcValues.providerTokensSlashed, + before.serviceProvider.tokensStaked + ); + assertEq( + afterServiceProvider.tokensProvisioned + calcValues.providerTokensSlashed, + before.serviceProvider.tokensProvisioned + ); + } + } + + // use struct to avoid 'stack too deep' error + struct CalcValues_CloseAllocation { + uint256 rewards; + uint256 delegatorRewards; + uint256 indexerRewards; + } + struct BeforeValues_CloseAllocation { + IHorizonStakingExtension.Allocation allocation; + DelegationPoolInternalTest pool; + ServiceProviderInternal serviceProvider; + uint256 subgraphAllocations; + uint256 stakingBalance; + uint256 indexerBalance; + uint256 beneficiaryBalance; + } + + // Current rewards manager is mocked and assumed to mint fixed rewards + function _closeAllocation(address allocationId, bytes32 poi) internal { + (, address msgSender, ) = vm.readCallers(); + + // before + BeforeValues_CloseAllocation memory beforeValues; + beforeValues.allocation = staking.getAllocation(allocationId); + beforeValues.pool = _getStorage_DelegationPoolInternal( + beforeValues.allocation.indexer, + subgraphDataServiceLegacyAddress, + true + ); + beforeValues.serviceProvider = _getStorage_ServiceProviderInternal(beforeValues.allocation.indexer); + beforeValues.subgraphAllocations = _getStorage_SubgraphAllocations( + beforeValues.allocation.subgraphDeploymentID + ); + beforeValues.stakingBalance = token.balanceOf(address(staking)); + beforeValues.indexerBalance = token.balanceOf(beforeValues.allocation.indexer); + beforeValues.beneficiaryBalance = token.balanceOf( + _getStorage_RewardsDestination(beforeValues.allocation.indexer) + ); + + bool isAuth = staking.isAuthorized( + msgSender, + beforeValues.allocation.indexer, + subgraphDataServiceLegacyAddress + ); + address rewardsDestination = _getStorage_RewardsDestination(beforeValues.allocation.indexer); + + CalcValues_CloseAllocation memory calcValues = CalcValues_CloseAllocation({ + rewards: ALLOCATIONS_REWARD_CUT, + delegatorRewards: ALLOCATIONS_REWARD_CUT - + uint256(beforeValues.pool.__DEPRECATED_indexingRewardCut).mulPPM(ALLOCATIONS_REWARD_CUT), + indexerRewards: 0 + }); + calcValues.indexerRewards = + ALLOCATIONS_REWARD_CUT - + (beforeValues.pool.tokens > 0 ? calcValues.delegatorRewards : 0); + + // closeAllocation + vm.expectEmit(address(staking)); + emit IHorizonStakingExtension.AllocationClosed( + beforeValues.allocation.indexer, + beforeValues.allocation.subgraphDeploymentID, + epochManager.currentEpoch(), + beforeValues.allocation.tokens, + allocationId, + msgSender, + poi, + !isAuth + ); + staking.closeAllocation(allocationId, poi); + + // after + IHorizonStakingExtension.Allocation memory afterAllocation = staking.getAllocation(allocationId); + DelegationPoolInternalTest memory afterPool = _getStorage_DelegationPoolInternal( + beforeValues.allocation.indexer, + subgraphDataServiceLegacyAddress, + true + ); + ServiceProviderInternal memory afterServiceProvider = _getStorage_ServiceProviderInternal( + beforeValues.allocation.indexer + ); + uint256 afterSubgraphAllocations = _getStorage_SubgraphAllocations( + beforeValues.allocation.subgraphDeploymentID + ); + uint256 afterStakingBalance = token.balanceOf(address(staking)); + uint256 afterIndexerBalance = token.balanceOf(beforeValues.allocation.indexer); + uint256 afterBeneficiaryBalance = token.balanceOf(rewardsDestination); + + if (beforeValues.allocation.tokens > 0) { + if (isAuth && poi != 0) { + if (rewardsDestination != address(0)) { + assertEq( + beforeValues.stakingBalance + calcValues.rewards - calcValues.indexerRewards, + afterStakingBalance + ); + assertEq(beforeValues.indexerBalance, afterIndexerBalance); + assertEq(beforeValues.beneficiaryBalance + calcValues.indexerRewards, afterBeneficiaryBalance); + } else { + assertEq(beforeValues.stakingBalance + calcValues.rewards, afterStakingBalance); + assertEq(beforeValues.indexerBalance, afterIndexerBalance); + assertEq(beforeValues.beneficiaryBalance, afterBeneficiaryBalance); + } + } else { + assertEq(beforeValues.stakingBalance, afterStakingBalance); + assertEq(beforeValues.indexerBalance, afterIndexerBalance); + assertEq(beforeValues.beneficiaryBalance, afterBeneficiaryBalance); + } + } else { + assertEq(beforeValues.stakingBalance, afterStakingBalance); + assertEq(beforeValues.indexerBalance, afterIndexerBalance); + assertEq(beforeValues.beneficiaryBalance, afterBeneficiaryBalance); + } + + assertEq(afterAllocation.indexer, beforeValues.allocation.indexer); + assertEq(afterAllocation.subgraphDeploymentID, beforeValues.allocation.subgraphDeploymentID); + assertEq(afterAllocation.tokens, beforeValues.allocation.tokens); + assertEq(afterAllocation.createdAtEpoch, beforeValues.allocation.createdAtEpoch); + assertEq(afterAllocation.closedAtEpoch, epochManager.currentEpoch()); + assertEq(afterAllocation.collectedFees, beforeValues.allocation.collectedFees); + assertEq( + afterAllocation.__DEPRECATED_effectiveAllocation, + beforeValues.allocation.__DEPRECATED_effectiveAllocation + ); + assertEq(afterAllocation.accRewardsPerAllocatedToken, beforeValues.allocation.accRewardsPerAllocatedToken); + assertEq(afterAllocation.distributedRebates, beforeValues.allocation.distributedRebates); + + if (beforeValues.allocation.tokens > 0 && isAuth && poi != 0 && rewardsDestination == address(0)) { + assertEq( + afterServiceProvider.tokensStaked, + beforeValues.serviceProvider.tokensStaked + calcValues.indexerRewards + ); + } else { + assertEq(afterServiceProvider.tokensStaked, beforeValues.serviceProvider.tokensStaked); + } + assertEq(afterServiceProvider.tokensProvisioned, beforeValues.serviceProvider.tokensProvisioned); + assertEq( + afterServiceProvider.__DEPRECATED_tokensAllocated + beforeValues.allocation.tokens, + beforeValues.serviceProvider.__DEPRECATED_tokensAllocated + ); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLocked, + beforeValues.serviceProvider.__DEPRECATED_tokensLocked + ); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLockedUntil, + beforeValues.serviceProvider.__DEPRECATED_tokensLockedUntil + ); + + assertEq(afterSubgraphAllocations + beforeValues.allocation.tokens, beforeValues.subgraphAllocations); + + if (beforeValues.allocation.tokens > 0 && isAuth && poi != 0 && beforeValues.pool.tokens > 0) { + assertEq(afterPool.tokens, beforeValues.pool.tokens + calcValues.delegatorRewards); + } else { + assertEq(afterPool.tokens, beforeValues.pool.tokens); + } + } + + // use struct to avoid 'stack too deep' error + struct BeforeValues_Collect { + IHorizonStakingExtension.Allocation allocation; + DelegationPoolInternalTest pool; + ServiceProviderInternal serviceProvider; + uint256 stakingBalance; + uint256 senderBalance; + uint256 curationBalance; + uint256 beneficiaryBalance; + } + struct CalcValues_Collect { + uint256 protocolTaxTokens; + uint256 queryFees; + uint256 curationCutTokens; + uint256 newRebates; + uint256 payment; + uint256 delegationFeeCut; + } + struct AfterValues_Collect { + IHorizonStakingExtension.Allocation allocation; + DelegationPoolInternalTest pool; + ServiceProviderInternal serviceProvider; + uint256 stakingBalance; + uint256 senderBalance; + uint256 curationBalance; + uint256 beneficiaryBalance; + } + + function _collect(uint256 tokens, address allocationId) internal { + (, address msgSender, ) = vm.readCallers(); + + // before + BeforeValues_Collect memory beforeValues; + beforeValues.allocation = staking.getAllocation(allocationId); + beforeValues.pool = _getStorage_DelegationPoolInternal( + beforeValues.allocation.indexer, + subgraphDataServiceLegacyAddress, + true + ); + beforeValues.serviceProvider = _getStorage_ServiceProviderInternal(beforeValues.allocation.indexer); + + (uint32 curationPercentage, uint32 protocolPercentage) = _getStorage_ProtocolTaxAndCuration(); + address rewardsDestination = _getStorage_RewardsDestination(beforeValues.allocation.indexer); + + beforeValues.stakingBalance = token.balanceOf(address(staking)); + beforeValues.senderBalance = token.balanceOf(msgSender); + beforeValues.curationBalance = token.balanceOf(address(curation)); + beforeValues.beneficiaryBalance = token.balanceOf(rewardsDestination); + + // calc some stuff + CalcValues_Collect memory calcValues; + calcValues.protocolTaxTokens = tokens.mulPPMRoundUp(protocolPercentage); + calcValues.queryFees = tokens - calcValues.protocolTaxTokens; + calcValues.curationCutTokens = 0; + if (curation.isCurated(beforeValues.allocation.subgraphDeploymentID)) { + calcValues.curationCutTokens = calcValues.queryFees.mulPPMRoundUp(curationPercentage); + calcValues.queryFees -= calcValues.curationCutTokens; + } + calcValues.newRebates = ExponentialRebates.exponentialRebates( + calcValues.queryFees + beforeValues.allocation.collectedFees, + beforeValues.allocation.tokens, + alphaNumerator, + alphaDenominator, + lambdaNumerator, + lambdaDenominator + ); + calcValues.payment = calcValues.newRebates > calcValues.queryFees + ? calcValues.queryFees + : calcValues.newRebates; + calcValues.delegationFeeCut = 0; + if (beforeValues.pool.tokens > 0) { + calcValues.delegationFeeCut = + calcValues.payment - + calcValues.payment.mulPPM(beforeValues.pool.__DEPRECATED_queryFeeCut); + calcValues.payment -= calcValues.delegationFeeCut; + } + + // staking.collect() + if (tokens > 0) { + vm.expectEmit(address(staking)); + emit IHorizonStakingExtension.RebateCollected( + msgSender, + beforeValues.allocation.indexer, + beforeValues.allocation.subgraphDeploymentID, + allocationId, + epochManager.currentEpoch(), + tokens, + calcValues.protocolTaxTokens, + calcValues.curationCutTokens, + calcValues.queryFees, + calcValues.payment, + calcValues.delegationFeeCut + ); + } + staking.collect(tokens, allocationId); + + // after + AfterValues_Collect memory afterValues; + afterValues.allocation = staking.getAllocation(allocationId); + afterValues.pool = _getStorage_DelegationPoolInternal( + beforeValues.allocation.indexer, + subgraphDataServiceLegacyAddress, + true + ); + afterValues.serviceProvider = _getStorage_ServiceProviderInternal(beforeValues.allocation.indexer); + afterValues.stakingBalance = token.balanceOf(address(staking)); + afterValues.senderBalance = token.balanceOf(msgSender); + afterValues.curationBalance = token.balanceOf(address(curation)); + afterValues.beneficiaryBalance = token.balanceOf(rewardsDestination); + + // assert + assertEq(afterValues.senderBalance + tokens, beforeValues.senderBalance); + assertEq(afterValues.curationBalance, beforeValues.curationBalance + calcValues.curationCutTokens); + if (rewardsDestination != address(0)) { + assertEq(afterValues.beneficiaryBalance, beforeValues.beneficiaryBalance + calcValues.payment); + assertEq(afterValues.stakingBalance, beforeValues.stakingBalance + calcValues.delegationFeeCut); + } else { + assertEq(afterValues.beneficiaryBalance, beforeValues.beneficiaryBalance); + assertEq( + afterValues.stakingBalance, + beforeValues.stakingBalance + calcValues.delegationFeeCut + calcValues.payment + ); + } + + assertEq( + afterValues.allocation.collectedFees, + beforeValues.allocation.collectedFees + tokens - calcValues.protocolTaxTokens - calcValues.curationCutTokens + ); + assertEq(afterValues.allocation.indexer, beforeValues.allocation.indexer); + assertEq(afterValues.allocation.subgraphDeploymentID, beforeValues.allocation.subgraphDeploymentID); + assertEq(afterValues.allocation.tokens, beforeValues.allocation.tokens); + assertEq(afterValues.allocation.createdAtEpoch, beforeValues.allocation.createdAtEpoch); + assertEq(afterValues.allocation.closedAtEpoch, beforeValues.allocation.closedAtEpoch); + assertEq( + afterValues.allocation.accRewardsPerAllocatedToken, + beforeValues.allocation.accRewardsPerAllocatedToken + ); + assertEq( + afterValues.allocation.distributedRebates, + beforeValues.allocation.distributedRebates + calcValues.newRebates + ); + + assertEq(afterValues.pool.tokens, beforeValues.pool.tokens + calcValues.delegationFeeCut); + assertEq(afterValues.pool.shares, beforeValues.pool.shares); + assertEq(afterValues.pool.tokensThawing, beforeValues.pool.tokensThawing); + assertEq(afterValues.pool.sharesThawing, beforeValues.pool.sharesThawing); + + assertEq(afterValues.serviceProvider.tokensProvisioned, beforeValues.serviceProvider.tokensProvisioned); + if (rewardsDestination != address(0)) { + assertEq(afterValues.serviceProvider.tokensStaked, beforeValues.serviceProvider.tokensStaked); + } else { + assertEq( + afterValues.serviceProvider.tokensStaked, + beforeValues.serviceProvider.tokensStaked + calcValues.payment + ); + } + } + + /* + * STORAGE HELPERS + */ + function _getStorage_ServiceProviderInternal( + address serviceProvider + ) internal view returns (ServiceProviderInternal memory) { + uint256 slotNumber = 14; + uint256 baseSlotUint = uint256(keccak256(abi.encode(serviceProvider, slotNumber))); + + ServiceProviderInternal memory serviceProviderInternal = ServiceProviderInternal({ + tokensStaked: uint256(vm.load(address(staking), bytes32(baseSlotUint))), + __DEPRECATED_tokensAllocated: uint256(vm.load(address(staking), bytes32(baseSlotUint + 1))), + __DEPRECATED_tokensLocked: uint256(vm.load(address(staking), bytes32(baseSlotUint + 2))), + __DEPRECATED_tokensLockedUntil: uint256(vm.load(address(staking), bytes32(baseSlotUint + 3))), + tokensProvisioned: uint256(vm.load(address(staking), bytes32(baseSlotUint + 4))) + }); + + return serviceProviderInternal; + } + + function _getStorage_OperatorAuth( + address serviceProvider, + address operator, + address verifier, + bool legacy + ) internal view returns (bool) { + uint256 slotNumber = legacy ? 21 : 31; + uint256 slot; + + if (legacy) { + slot = uint256(keccak256(abi.encode(operator, keccak256(abi.encode(serviceProvider, slotNumber))))); + } else { + slot = uint256( + keccak256( + abi.encode( + operator, + keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, slotNumber)))) + ) + ) + ); + } + return vm.load(address(staking), bytes32(slot)) == bytes32(uint256(1)); + } + + function _setStorage_DeprecatedThawingPeriod(uint32 _thawingPeriod) internal { + uint256 slot = 13; + + // Read the current value of the slot + uint256 currentSlotValue = uint256(vm.load(address(staking), bytes32(slot))); + + // Create a mask to clear the bits for __DEPRECATED_thawingPeriod (bits 0-31) + uint256 mask = ~(uint256(0xFFFFFFFF)); // Mask to clear the first 32 bits + + // Clear the bits for __DEPRECATED_thawingPeriod and set the new value + uint256 newSlotValue = (currentSlotValue & mask) | uint256(_thawingPeriod); + + // Store the updated value back into the slot + vm.store(address(staking), bytes32(slot), bytes32(newSlotValue)); + } + + function _setStorage_ServiceProvider( + address _indexer, + uint256 _tokensStaked, + uint256 _tokensAllocated, + uint256 _tokensLocked, + uint256 _tokensLockedUntil, + uint256 _tokensProvisioned + ) internal { + uint256 serviceProviderSlot = 14; + bytes32 serviceProviderBaseSlot = keccak256(abi.encode(_indexer, serviceProviderSlot)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot)), bytes32(_tokensStaked)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 1), bytes32(_tokensAllocated)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 2), bytes32(_tokensLocked)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 3), bytes32(_tokensLockedUntil)); + vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 4), bytes32(_tokensProvisioned)); + } + + // DelegationPoolInternal contains a mapping, solidity doesn't allow constructing structs with + // nested mappings on memory: "Struct containing a (nested) mapping cannot be constructed" + // So we use a custom struct here and remove the nested mapping which we don't need anyways + struct DelegationPoolInternalTest { + // (Deprecated) Time, in blocks, an indexer must wait before updating delegation parameters + uint32 __DEPRECATED_cooldownBlocks; + // (Deprecated) Percentage of indexing rewards for the service provider, in PPM + uint32 __DEPRECATED_indexingRewardCut; + // (Deprecated) Percentage of query fees for the service provider, in PPM + uint32 __DEPRECATED_queryFeeCut; + // (Deprecated) Block when the delegation parameters were last updated + uint256 __DEPRECATED_updatedAtBlock; + // Total tokens as pool reserves + uint256 tokens; + // Total shares minted in the pool + uint256 shares; + // Delegation details by delegator + uint256 _gap_delegators_mapping; + // Tokens thawing in the pool + uint256 tokensThawing; + // Shares representing the thawing tokens + uint256 sharesThawing; + } + + function _getStorage_DelegationPoolInternal( + address serviceProvider, + address verifier, + bool legacy + ) internal view returns (DelegationPoolInternalTest memory) { + uint256 slotNumber = legacy ? 20 : 33; + uint256 baseSlot; + if (legacy) { + baseSlot = uint256(keccak256(abi.encode(serviceProvider, slotNumber))); + } else { + baseSlot = uint256(keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, slotNumber))))); + } + + uint256 packedData = uint256(vm.load(address(staking), bytes32(baseSlot))); + + DelegationPoolInternalTest memory delegationPoolInternal = DelegationPoolInternalTest({ + __DEPRECATED_cooldownBlocks: uint32(packedData & 0xFFFFFFFF), + __DEPRECATED_indexingRewardCut: uint32((packedData >> 32) & 0xFFFFFFFF), + __DEPRECATED_queryFeeCut: uint32((packedData >> 64) & 0xFFFFFFFF), + __DEPRECATED_updatedAtBlock: uint256(vm.load(address(staking), bytes32(baseSlot + 1))), + tokens: uint256(vm.load(address(staking), bytes32(baseSlot + 2))), + shares: uint256(vm.load(address(staking), bytes32(baseSlot + 3))), + _gap_delegators_mapping: uint256(vm.load(address(staking), bytes32(baseSlot + 4))), + tokensThawing: uint256(vm.load(address(staking), bytes32(baseSlot + 5))), + sharesThawing: uint256(vm.load(address(staking), bytes32(baseSlot + 6))) + }); + + return delegationPoolInternal; + } + + function _getStorage_Delegation( + address serviceProvider, + address verifier, + address delegator, + bool legacy + ) internal view returns (DelegationInternal memory) { + uint256 slotNumber = legacy ? 20 : 33; + uint256 baseSlot; + + // DelegationPool + if (legacy) { + baseSlot = uint256(keccak256(abi.encode(serviceProvider, slotNumber))); + } else { + baseSlot = uint256(keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, slotNumber))))); + } + + // delegators slot in DelegationPool + baseSlot += 4; + + // Delegation + baseSlot = uint256(keccak256(abi.encode(delegator, baseSlot))); + + DelegationInternal memory delegation = DelegationInternal({ + shares: uint256(vm.load(address(staking), bytes32(baseSlot))), + __DEPRECATED_tokensLocked: uint256(vm.load(address(staking), bytes32(baseSlot + 1))), + __DEPRECATED_tokensLockedUntil: uint256(vm.load(address(staking), bytes32(baseSlot + 2))) + }); + + return delegation; + } + + function _getStorage_CounterpartStakingAddress() internal view returns (address) { + uint256 slot = 24; + return address(uint160(uint256(vm.load(address(staking), bytes32(slot))))); + } + + function _setStorage_allocation( + IHorizonStakingExtension.Allocation memory allocation, + address allocationId, + uint256 tokens + ) internal { + // __DEPRECATED_allocations + uint256 allocationsSlot = 15; + bytes32 allocationBaseSlot = keccak256(abi.encode(allocationId, allocationsSlot)); + vm.store(address(staking), allocationBaseSlot, bytes32(uint256(uint160(allocation.indexer)))); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 1), allocation.subgraphDeploymentID); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 2), bytes32(tokens)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 3), bytes32(allocation.createdAtEpoch)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 4), bytes32(allocation.closedAtEpoch)); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 5), bytes32(allocation.collectedFees)); + vm.store( + address(staking), + bytes32(uint256(allocationBaseSlot) + 6), + bytes32(allocation.__DEPRECATED_effectiveAllocation) + ); + vm.store( + address(staking), + bytes32(uint256(allocationBaseSlot) + 7), + bytes32(allocation.accRewardsPerAllocatedToken) + ); + vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 8), bytes32(allocation.distributedRebates)); + + // _serviceProviders + uint256 serviceProviderSlot = 14; + bytes32 serviceProviderBaseSlot = keccak256(abi.encode(allocation.indexer, serviceProviderSlot)); + uint256 currentTokensStaked = uint256(vm.load(address(staking), serviceProviderBaseSlot)); + uint256 currentTokensProvisioned = uint256( + vm.load(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 1)) + ); + vm.store( + address(staking), + bytes32(uint256(serviceProviderBaseSlot) + 0), + bytes32(currentTokensStaked + tokens) + ); + vm.store( + address(staking), + bytes32(uint256(serviceProviderBaseSlot) + 1), + bytes32(currentTokensProvisioned + tokens) + ); + + // __DEPRECATED_subgraphAllocations + uint256 subgraphsAllocationsSlot = 16; + bytes32 subgraphAllocationsBaseSlot = keccak256( + abi.encode(allocation.subgraphDeploymentID, subgraphsAllocationsSlot) + ); + uint256 currentAllocatedTokens = uint256(vm.load(address(staking), subgraphAllocationsBaseSlot)); + vm.store(address(staking), subgraphAllocationsBaseSlot, bytes32(currentAllocatedTokens + tokens)); + } + + function _getStorage_SubgraphAllocations(bytes32 subgraphDeploymentID) internal view returns (uint256) { + uint256 subgraphsAllocationsSlot = 16; + bytes32 subgraphAllocationsBaseSlot = keccak256(abi.encode(subgraphDeploymentID, subgraphsAllocationsSlot)); + return uint256(vm.load(address(staking), subgraphAllocationsBaseSlot)); + } + + function _setStorage_RewardsDestination(address serviceProvider, address destination) internal { + uint256 rewardsDestinationSlot = 23; + bytes32 rewardsDestinationSlotBaseSlot = keccak256(abi.encode(serviceProvider, rewardsDestinationSlot)); + vm.store(address(staking), rewardsDestinationSlotBaseSlot, bytes32(uint256(uint160(destination)))); + } + + function _getStorage_RewardsDestination(address serviceProvider) internal view returns (address) { + uint256 rewardsDestinationSlot = 23; + bytes32 rewardsDestinationSlotBaseSlot = keccak256(abi.encode(serviceProvider, rewardsDestinationSlot)); + return address(uint160(uint256(vm.load(address(staking), rewardsDestinationSlotBaseSlot)))); + } + + function _setStorage_MaxAllocationEpochs(uint256 maxAllocationEpochs) internal { + uint256 slot = 13; + + // Read the current value of the storage slot + uint256 currentSlotValue = uint256(vm.load(address(staking), bytes32(slot))); + + // Mask to clear the specific bits for __DEPRECATED_maxAllocationEpochs (bits 128-159) + uint256 mask = ~(uint256(0xFFFFFFFF) << 128); + + // Clear the bits and set the new maxAllocationEpochs value + uint256 newSlotValue = (currentSlotValue & mask) | (uint256(maxAllocationEpochs) << 128); + + // Store the updated value back into the slot + vm.store(address(staking), bytes32(slot), bytes32(newSlotValue)); + + uint256 readMaxAllocationEpochs = _getStorage_MaxAllocationEpochs(); + assertEq(readMaxAllocationEpochs, maxAllocationEpochs); + } + + function _getStorage_MaxAllocationEpochs() internal view returns (uint256) { + uint256 slot = 13; + + // Read the current value of the storage slot + uint256 currentSlotValue = uint256(vm.load(address(staking), bytes32(slot))); + + // Mask to isolate bits 128-159 + uint256 mask = uint256(0xFFFFFFFF) << 128; + + // Extract the maxAllocationEpochs by masking and shifting + uint256 maxAllocationEpochs = (currentSlotValue & mask) >> 128; + + return maxAllocationEpochs; + } + + function _setStorage_DelegationPool( + address serviceProvider, + uint256 tokens, + uint32 indexingRewardCut, + uint32 queryFeeCut + ) internal { + bytes32 baseSlot = keccak256(abi.encode(serviceProvider, uint256(20))); + bytes32 feeCutValues = bytes32( + (uint256(indexingRewardCut) << uint256(32)) | (uint256(queryFeeCut) << uint256(64)) + ); + bytes32 tokensSlot = bytes32(uint256(baseSlot) + 2); + vm.store(address(staking), baseSlot, feeCutValues); + vm.store(address(staking), tokensSlot, bytes32(tokens)); + } + + function _setStorage_RebateParameters( + uint32 alphaNumerator_, + uint32 alphaDenominator_, + uint32 lambdaNumerator_, + uint32 lambdaDenominator_ + ) internal { + // Store alpha numerator and denominator in slot 13 + uint256 alphaSlot = 13; + + uint256 newAlphaSlotValue; + { + uint256 alphaNumeratorOffset = 160; // Offset for __DEPRECATED_alphaNumerator (20th byte) + uint256 alphaDenominatorOffset = 192; // Offset for __DEPRECATED_alphaDenominator (24th byte) + + // Read current value of the slot + uint256 currentAlphaSlotValue = uint256(vm.load(address(staking), bytes32(alphaSlot))); + + // Create a mask to clear the bits for alphaNumerator and alphaDenominator + uint256 alphaMask = ~(uint256(0xFFFFFFFF) << alphaNumeratorOffset) & + ~(uint256(0xFFFFFFFF) << alphaDenominatorOffset); + + // Clear and set new values + newAlphaSlotValue = + (currentAlphaSlotValue & alphaMask) | + (uint256(alphaNumerator_) << alphaNumeratorOffset) | + (uint256(alphaDenominator_) << alphaDenominatorOffset); + } + + // Store the updated value back into the slot + vm.store(address(staking), bytes32(alphaSlot), bytes32(newAlphaSlotValue)); + + // Store lambda numerator and denominator in slot 25 + uint256 lambdaSlot = 25; + + uint256 newLambdaSlotValue; + { + uint256 lambdaNumeratorOffset = 160; // Offset for lambdaNumerator (20th byte) + uint256 lambdaDenominatorOffset = 192; // Offset for lambdaDenominator (24th byte) + + // Read current value of the slot + uint256 currentLambdaSlotValue = uint256(vm.load(address(staking), bytes32(lambdaSlot))); + + // Create a mask to clear the bits for lambdaNumerator and lambdaDenominator + uint256 lambdaMask = ~(uint256(0xFFFFFFFF) << lambdaNumeratorOffset) & + ~(uint256(0xFFFFFFFF) << lambdaDenominatorOffset); + + // Clear and set new values + newLambdaSlotValue = + (currentLambdaSlotValue & lambdaMask) | + (uint256(lambdaNumerator_) << lambdaNumeratorOffset) | + (uint256(lambdaDenominator_) << lambdaDenominatorOffset); + } + + // Store the updated value back into the slot + vm.store(address(staking), bytes32(lambdaSlot), bytes32(newLambdaSlotValue)); + + // Verify the storage + ( + uint32 readAlphaNumerator, + uint32 readAlphaDenominator, + uint32 readLambdaNumerator, + uint32 readLambdaDenominator + ) = _getStorage_RebateParameters(); + assertEq(readAlphaNumerator, alphaNumerator_); + assertEq(readAlphaDenominator, alphaDenominator_); + assertEq(readLambdaNumerator, lambdaNumerator_); + assertEq(readLambdaDenominator, lambdaDenominator_); + } + + function _getStorage_RebateParameters() internal view returns (uint32, uint32, uint32, uint32) { + // Read alpha numerator and denominator + uint256 alphaSlot = 13; + uint256 alphaValues = uint256(vm.load(address(staking), bytes32(alphaSlot))); + uint32 alphaNumerator_ = uint32(alphaValues >> 160); + uint32 alphaDenominator_ = uint32(alphaValues >> 192); + + // Read lambda numerator and denominator + uint256 lambdaSlot = 25; + uint256 lambdaValues = uint256(vm.load(address(staking), bytes32(lambdaSlot))); + uint32 lambdaNumerator_ = uint32(lambdaValues >> 160); + uint32 lambdaDenominator_ = uint32(lambdaValues >> 192); + + return (alphaNumerator_, alphaDenominator_, lambdaNumerator_, lambdaDenominator_); + } + + // function _setStorage_ProtocolTaxAndCuration(uint32 curationPercentage, uint32 taxPercentage) private { + // bytes32 slot = bytes32(uint256(13)); + // uint256 curationOffset = 4; + // uint256 protocolTaxOffset = 8; + // bytes32 originalValue = vm.load(address(staking), slot); + + // bytes32 newProtocolTaxValue = bytes32( + // ((uint256(originalValue) & + // ~((0xFFFFFFFF << (8 * curationOffset)) | (0xFFFFFFFF << (8 * protocolTaxOffset)))) | + // (uint256(curationPercentage) << (8 * curationOffset))) | + // (uint256(taxPercentage) << (8 * protocolTaxOffset)) + // ); + // vm.store(address(staking), slot, newProtocolTaxValue); + + // (uint32 readCurationPercentage, uint32 readTaxPercentage) = _getStorage_ProtocolTaxAndCuration(); + // assertEq(readCurationPercentage, curationPercentage); + // } + + function _setStorage_ProtocolTaxAndCuration(uint32 curationPercentage, uint32 taxPercentage) internal { + bytes32 slot = bytes32(uint256(13)); + + // Offsets for the percentages + uint256 curationOffset = 32; // __DEPRECATED_curationPercentage (2nd uint32, bits 32-63) + uint256 protocolTaxOffset = 64; // __DEPRECATED_protocolPercentage (3rd uint32, bits 64-95) + + // Read the current slot value + uint256 originalValue = uint256(vm.load(address(staking), slot)); + + // Create masks to clear the specific bits for the two percentages + uint256 mask = ~(uint256(0xFFFFFFFF) << curationOffset) & ~(uint256(0xFFFFFFFF) << protocolTaxOffset); // Mask for curationPercentage // Mask for protocolTax + + // Clear the existing bits and set the new values + uint256 newSlotValue = (originalValue & mask) | + (uint256(curationPercentage) << curationOffset) | + (uint256(taxPercentage) << protocolTaxOffset); + + // Store the updated slot value + vm.store(address(staking), slot, bytes32(newSlotValue)); + + // Verify the values were set correctly + (uint32 readCurationPercentage, uint32 readTaxPercentage) = _getStorage_ProtocolTaxAndCuration(); + assertEq(readCurationPercentage, curationPercentage); + assertEq(readTaxPercentage, taxPercentage); + } + + function _getStorage_ProtocolTaxAndCuration() internal view returns (uint32, uint32) { + bytes32 slot = bytes32(uint256(13)); + bytes32 value = vm.load(address(staking), slot); + uint32 curationPercentage = uint32(uint256(value) >> 32); + uint32 taxPercentage = uint32(uint256(value) >> 64); + return (curationPercentage, taxPercentage); + } + + /* + * MISC: private functions to help with testing + */ + // use struct to avoid 'stack too deep' error + struct CalcValues_ThawRequestData { + uint256 tokensThawed; + uint256 tokensThawing; + uint256 sharesThawing; + ThawRequest[] thawRequestsFulfilledList; + bytes32[] thawRequestsFulfilledListIds; + uint256[] thawRequestsFulfilledListTokens; + } + + function calcThawRequestData( + address serviceProvider, + address verifier, + address owner, + uint256 iterations, + bool delegation + ) private view returns (CalcValues_ThawRequestData memory) { + LinkedList.List memory thawRequestList = staking.getThawRequestList(serviceProvider, verifier, owner); + if (thawRequestList.count == 0) { + return CalcValues_ThawRequestData(0, 0, 0, new ThawRequest[](0), new bytes32[](0), new uint256[](0)); + } + + Provision memory prov = staking.getProvision(serviceProvider, verifier); + DelegationPool memory pool = staking.getDelegationPool(serviceProvider, verifier); + + uint256 tokensThawed = 0; + uint256 tokensThawing = delegation ? pool.tokensThawing : prov.tokensThawing; + uint256 sharesThawing = delegation ? pool.sharesThawing : prov.sharesThawing; + uint256 thawRequestsFulfilled = 0; + + bytes32 thawRequestId = thawRequestList.head; + while (thawRequestId != bytes32(0) && (iterations == 0 || thawRequestsFulfilled < iterations)) { + ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + if (thawRequest.thawingUntil <= block.timestamp) { + thawRequestsFulfilled++; + uint256 tokens = delegation + ? (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing + : (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; + tokensThawed += tokens; + tokensThawing -= tokens; + sharesThawing -= thawRequest.shares; + } else { + break; + } + thawRequestId = thawRequest.next; + } + + // we need to do a second pass because solidity doesnt allow dynamic arrays on memory + ThawRequest[] memory thawRequestsFulfilledList = new ThawRequest[](thawRequestsFulfilled); + bytes32[] memory thawRequestsFulfilledListIds = new bytes32[](thawRequestsFulfilled); + uint256[] memory thawRequestsFulfilledListTokens = new uint256[](thawRequestsFulfilled); + uint256 i = 0; + thawRequestId = thawRequestList.head; + while (thawRequestId != bytes32(0) && (iterations == 0 || i < iterations)) { + ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + if (thawRequest.thawingUntil <= block.timestamp) { + uint256 tokens = delegation + ? (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing + : (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; + thawRequestsFulfilledListTokens[i] = tokens; + thawRequestsFulfilledListIds[i] = thawRequestId; + thawRequestsFulfilledList[i] = staking.getThawRequest(thawRequestId); + thawRequestId = thawRequestsFulfilledList[i].next; + i++; + } else { + break; + } + thawRequestId = thawRequest.next; + } + + assertEq(thawRequestsFulfilled, thawRequestsFulfilledList.length); + assertEq(thawRequestsFulfilled, thawRequestsFulfilledListIds.length); + assertEq(thawRequestsFulfilled, thawRequestsFulfilledListTokens.length); + + return + CalcValues_ThawRequestData( + tokensThawed, + tokensThawing, + sharesThawing, + thawRequestsFulfilledList, + thawRequestsFulfilledListIds, + thawRequestsFulfilledListTokens + ); } } diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index 1973f8581..d846d1754 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -1,17 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; -import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; -import { IHorizonStakingTypes } from "../../contracts/interfaces/internal/IHorizonStakingTypes.sol"; -import { LinkedList } from "../../contracts/libraries/LinkedList.sol"; -import { MathUtils } from "../../contracts/libraries/MathUtils.sol"; - import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; -contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { +contract HorizonStakingTest is HorizonStakingSharedTest { using stdStorage for StdStorage; /* @@ -25,38 +20,11 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { _; } - modifier useOperator() { - vm.startPrank(users.indexer); - staking.setOperator(users.operator, subgraphDataServiceAddress, true); - vm.startPrank(users.operator); - _; - vm.stopPrank(); - } - - modifier useStake(uint256 amount) { - vm.assume(amount > 0); - approve(address(staking), amount); - staking.stake(amount); - _; - } - - modifier useStakeTo(address to, uint256 amount) { - vm.assume(amount > 0); - _stakeTo(to, amount); - _; - } - - modifier useThawRequest(uint256 thawAmount) { - vm.assume(thawAmount > 0); - _createThawRequest(thawAmount); - _; - } - modifier useThawAndDeprovision(uint256 amount, uint64 thawingPeriod) { vm.assume(amount > 0); - _createThawRequest(amount); + _thaw(users.indexer, subgraphDataServiceAddress, amount); skip(thawingPeriod + 1); - _deprovision(0); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); _; } @@ -75,7 +43,7 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { address msgSender; (, msgSender, ) = vm.readCallers(); resetPrank(users.governor); - staking.setAllowedLockedVerifier(verifier, true); + _setAllowedLockedVerifier(verifier, true); resetPrank(msgSender); _; } @@ -88,270 +56,4 @@ contract HorizonStakingTest is HorizonStakingSharedTest, IHorizonStakingTypes { resetPrank(msgSender); _; } - - /* - * HELPERS - */ - - function _stakeTo(address to, uint256 amount) internal { - approve(address(staking), amount); - staking.stakeTo(to, amount); - } - - function _createThawRequest(uint256 thawAmount) internal returns (bytes32) { - return staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); - } - - function _deprovision(uint256 nThawRequests) internal { - staking.deprovision(users.indexer, subgraphDataServiceAddress, nThawRequests); - } - - function _delegate(address serviceProvider, address verifier, uint256 tokens, uint256 minSharesOut) internal { - __delegate(serviceProvider, verifier, tokens, minSharesOut, false); - } - - function _delegateLegacy(address serviceProvider, uint256 tokens) internal { - __delegate(serviceProvider, subgraphDataServiceLegacyAddress, tokens, 0, true); - } - - - struct DelegateData { - DelegationPool pool; - Delegation delegation; - uint256 storagePoolTokens; - uint256 delegatedTokens; - uint256 delegatorBalance; - uint256 stakingBalance; - } - - function __delegate( - address serviceProvider, - address verifier, - uint256 tokens, - uint256 minSharesOut, - bool legacy - ) internal { - (, address delegator, ) = vm.readCallers(); - - // before - DelegateData memory beforeData = DelegateData({ - pool: staking.getDelegationPool(serviceProvider, verifier), - delegation: staking.getDelegation(serviceProvider, verifier, delegator), - storagePoolTokens: uint256(vm.load(address(staking), _getSlotPoolTokens(serviceProvider, verifier, legacy))), - delegatedTokens: staking.getDelegatedTokensAvailable(serviceProvider, verifier), - delegatorBalance: token.balanceOf(delegator), - stakingBalance: token.balanceOf(address(staking)) - }); - - uint256 calcShares = (beforeData.pool.tokens == 0 || beforeData.pool.tokens == beforeData.pool.tokensThawing) - ? tokens - : ((tokens * beforeData.pool.shares) / (beforeData.pool.tokens - beforeData.pool.tokensThawing)); - - // delegate - token.approve(address(staking), tokens); - vm.expectEmit(); - emit IHorizonStakingMain.TokensDelegated(serviceProvider, verifier, delegator, tokens); - if (legacy) { - staking.delegate(serviceProvider, tokens); - } else { - staking.delegate(serviceProvider, verifier, tokens, minSharesOut); - } - - // after - DelegateData memory afterData = DelegateData({ - pool: staking.getDelegationPool(serviceProvider, verifier), - delegation: staking.getDelegation(serviceProvider, verifier, delegator), - storagePoolTokens: uint256(vm.load(address(staking), _getSlotPoolTokens(serviceProvider, verifier, legacy))), - delegatedTokens: staking.getDelegatedTokensAvailable(serviceProvider, verifier), - delegatorBalance: token.balanceOf(delegator), - stakingBalance: token.balanceOf(address(staking)) - }); - - uint256 deltaShares = afterData.delegation.shares - beforeData.delegation.shares; - - // assertions - assertEq(beforeData.pool.tokens + tokens, afterData.pool.tokens); - assertEq(beforeData.pool.shares + calcShares, afterData.pool.shares); - assertEq(beforeData.pool.tokensThawing, afterData.pool.tokensThawing); - assertEq(beforeData.pool.sharesThawing, afterData.pool.sharesThawing); - assertGe(deltaShares, minSharesOut); - assertEq(calcShares, deltaShares); - assertEq(beforeData.delegatedTokens + tokens, afterData.delegatedTokens); - // Ensure correct slot is being updated, pools are stored in different storage locations for legacy subgraph data service - assertEq(beforeData.storagePoolTokens + tokens, afterData.storagePoolTokens); - assertEq(beforeData.delegatorBalance - tokens, afterData.delegatorBalance); - assertEq(beforeData.stakingBalance + tokens, afterData.stakingBalance); - } - - function _undelegate(address serviceProvider, address verifier, uint256 shares) internal { - __undelegate(serviceProvider, verifier, shares, false); - } - - function _undelegateLegacy(address serviceProvider, uint256 shares) internal { - __undelegate(serviceProvider, subgraphDataServiceLegacyAddress, shares, true); - } - - function __undelegate(address serviceProvider, address verifier, uint256 shares, bool legacy) internal { - (, address delegator, ) = vm.readCallers(); - - // Delegation pool data is stored in a different storage slot for the legacy subgraph data service - bytes32 slotPoolShares; - if (legacy) { - slotPoolShares = bytes32(uint256(keccak256(abi.encode(serviceProvider, 20))) + 3); - } else { - slotPoolShares = bytes32( - uint256(keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, 33))))) + 3 - ); - } - - // before - DelegationPool memory beforePool = staking.getDelegationPool(serviceProvider, verifier); - Delegation memory beforeDelegation = staking.getDelegation(serviceProvider, verifier, delegator); - LinkedList.List memory beforeThawRequestList = staking.getThawRequestList(serviceProvider, verifier, delegator); - uint256 beforeStoragePoolShares = uint256(vm.load(address(staking), slotPoolShares)); - uint256 beforeDelegatedTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); - - uint256 calcTokens = ((beforePool.tokens - beforePool.tokensThawing) * shares) / beforePool.shares; - uint256 calcThawingShares = beforePool.tokensThawing == 0 - ? calcTokens - : (beforePool.sharesThawing * calcTokens) / beforePool.tokensThawing; - uint64 calcThawingUntil = staking.getProvision(serviceProvider, verifier).thawingPeriod + - uint64(block.timestamp); - bytes32 calcThawRequestId = keccak256( - abi.encodePacked(serviceProvider, verifier, delegator, beforeThawRequestList.nonce) - ); - - // undelegate - vm.expectEmit(); - emit IHorizonStakingMain.ThawRequestCreated( - serviceProvider, - verifier, - delegator, - calcThawingShares, - calcThawingUntil, - calcThawRequestId - ); - vm.expectEmit(); - emit IHorizonStakingMain.TokensUndelegated(serviceProvider, verifier, delegator, calcTokens); - if (legacy) { - staking.undelegate(serviceProvider, shares); - } else { - staking.undelegate(serviceProvider, verifier, shares); - } - - // after - DelegationPool memory afterPool = staking.getDelegationPool(users.indexer, verifier); - Delegation memory afterDelegation = staking.getDelegation(serviceProvider, verifier, delegator); - LinkedList.List memory afterThawRequestList = staking.getThawRequestList(serviceProvider, verifier, delegator); - ThawRequest memory afterThawRequest = staking.getThawRequest(calcThawRequestId); - uint256 afterStoragePoolShares = uint256(vm.load(address(staking), slotPoolShares)); - uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); - - // assertions - assertEq(beforePool.shares, afterPool.shares + shares); - assertEq(beforePool.tokens, afterPool.tokens); - assertEq(beforePool.tokensThawing + calcTokens, afterPool.tokensThawing); - assertEq(beforePool.sharesThawing + calcThawingShares, afterPool.sharesThawing); - assertEq(beforeDelegation.shares - shares, afterDelegation.shares); - assertEq(afterThawRequest.shares, calcThawingShares); - assertEq(afterThawRequest.thawingUntil, calcThawingUntil); - assertEq(afterThawRequest.next, bytes32(0)); - assertEq(calcThawRequestId, afterThawRequestList.tail); - assertEq(beforeThawRequestList.nonce + 1, afterThawRequestList.nonce); - assertEq(beforeThawRequestList.count + 1, afterThawRequestList.count); - assertEq(afterDelegatedTokens + calcTokens, beforeDelegatedTokens); - // Ensure correct slot is being updated, pools are stored in different storage locations for legacy subgraph data service - assertEq(beforeStoragePoolShares, afterStoragePoolShares + shares); - } - - // todo remove these - function _getDelegation(address verifier) internal view returns (Delegation memory) { - return staking.getDelegation(users.indexer, verifier, users.delegator); - } - - function _getDelegationPool(address verifier) internal view returns (DelegationPool memory) { - return staking.getDelegationPool(users.indexer, verifier); - } - - function _storeServiceProvider( - address _indexer, - uint256 _tokensStaked, - uint256 _tokensAllocated, - uint256 _tokensLocked, - uint256 _tokensLockedUntil, - uint256 _tokensProvisioned - ) internal { - uint256 serviceProviderSlot = 14; - bytes32 serviceProviderBaseSlot = keccak256(abi.encode(_indexer, serviceProviderSlot)); - vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot)), bytes32(_tokensStaked)); - vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 1), bytes32(_tokensAllocated)); - vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 2), bytes32(_tokensLocked)); - vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 3), bytes32(_tokensLockedUntil)); - vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 4), bytes32(_tokensProvisioned)); - } - - function _slash(address serviceProvider, address verifier, uint256 tokens, uint256 verifierCutAmount) internal { - uint256 beforeProviderTokens = staking.getProviderTokensAvailable(serviceProvider, verifier); - uint256 beforeDelegationTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); - bool isDelegationSlashingEnabled = staking.isDelegationSlashingEnabled(); - - // Calculate expected tokens after slashing - uint256 providerTokensSlashed = MathUtils.min(beforeProviderTokens, tokens); - uint256 expectedProviderTokensAfterSlashing = beforeProviderTokens - providerTokensSlashed; - - uint256 delegationTokensSlashed = MathUtils.min(beforeDelegationTokens, tokens - providerTokensSlashed); - uint256 expectedDelegationTokensAfterSlashing = beforeDelegationTokens - - (isDelegationSlashingEnabled ? delegationTokensSlashed : 0); - - vm.expectEmit(address(staking)); - if (verifierCutAmount > 0) { - emit IHorizonStakingMain.VerifierTokensSent( - serviceProvider, - verifier, - verifier, - verifierCutAmount - ); - } - emit IHorizonStakingMain.ProvisionSlashed(serviceProvider, verifier, providerTokensSlashed); - - if (isDelegationSlashingEnabled) { - emit IHorizonStakingMain.DelegationSlashed( - serviceProvider, - verifier, - delegationTokensSlashed - ); - } else { - emit IHorizonStakingMain.DelegationSlashingSkipped( - serviceProvider, - verifier, - delegationTokensSlashed - ); - } - staking.slash(serviceProvider, tokens, verifierCutAmount, verifier); - - if (!isDelegationSlashingEnabled) { - expectedDelegationTokensAfterSlashing = beforeDelegationTokens; - } - - uint256 provisionTokens = staking.getProviderTokensAvailable(serviceProvider, verifier); - assertEq(provisionTokens, expectedProviderTokensAfterSlashing); - - uint256 delegationTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); - assertEq(delegationTokens, expectedDelegationTokensAfterSlashing); - - uint256 verifierTokens = token.balanceOf(verifier); - assertEq(verifierTokens, verifierCutAmount); - } - - function _getSlotPoolTokens(address serviceProvider, address verifier, bool legacy) private returns (bytes32) { - bytes32 slotPoolTokens; - if (legacy) { - slotPoolTokens = bytes32(uint256(keccak256(abi.encode(serviceProvider, 20))) + 2); - } else { - slotPoolTokens = bytes32( - uint256(keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, 33))))) + 2 - ); - } - return slotPoolTokens; - } } diff --git a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol b/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol deleted file mode 100644 index bf9524c43..000000000 --- a/packages/horizon/test/staking/allocation/HorizonStakingExtension.t.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import "forge-std/Test.sol"; - -import { HorizonStakingTest } from "../HorizonStaking.t.sol"; -import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; - -contract HorizonStakingExtensionTest is HorizonStakingTest { - - /* - * VARIABLES - */ - - address internal _allocationId = makeAddr("allocationId"); - bytes32 internal constant _subgraphDeploymentID = keccak256("subgraphDeploymentID"); - bytes32 internal constant _poi = keccak256("poi"); - uint256 internal constant MAX_ALLOCATION_EPOCHS = 28; - IHorizonStakingExtension.Allocation internal _allocation; - - /* - * MODIFIERS - */ - - modifier useAllocation() { - _storeAllocation(0); - _; - } - - /* - * SET UP - */ - - function setUp() public virtual override { - super.setUp(); - - _allocation = IHorizonStakingExtension.Allocation({ - indexer: users.indexer, - subgraphDeploymentID: _subgraphDeploymentID, - tokens: 0, - createdAtEpoch: block.timestamp, - closedAtEpoch: 0, - collectedFees: 0, - __DEPRECATED_effectiveAllocation: 0, - accRewardsPerAllocatedToken: 0, - distributedRebates: 0 - }); - } - - function _storeDelegationPool(uint256 tokens, uint32 indexingRewardCut, uint32 queryFeeCut) internal { - bytes32 baseSlot = keccak256(abi.encode(users.indexer, uint256(20))); - bytes32 feeCutValues = bytes32( - (uint256(indexingRewardCut) << uint256(32)) | - (uint256(queryFeeCut) << uint256(64)) - ); - bytes32 tokensSlot = bytes32(uint256(baseSlot) + 2); - vm.store(address(staking), baseSlot, feeCutValues); - vm.store(address(staking), tokensSlot, bytes32(tokens)); - } - - /* - * HELPERS - */ - - function _storeAllocation(uint256 tokens) internal { - uint256 allocationsSlot = 15; - bytes32 allocationBaseSlot = keccak256(abi.encode(_allocationId, allocationsSlot)); - vm.store(address(staking), allocationBaseSlot, bytes32(uint256(uint160(_allocation.indexer)))); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 1), _allocation.subgraphDeploymentID); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 2), bytes32(tokens)); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 3), bytes32(_allocation.createdAtEpoch)); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 4), bytes32(_allocation.closedAtEpoch)); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 5), bytes32(_allocation.collectedFees)); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 6), bytes32(_allocation.__DEPRECATED_effectiveAllocation)); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 7), bytes32(_allocation.accRewardsPerAllocatedToken)); - vm.store(address(staking), bytes32(uint256(allocationBaseSlot) + 8), bytes32(_allocation.distributedRebates)); - - uint256 serviceProviderSlot = 14; - bytes32 serviceProviderBaseSlot = keccak256(abi.encode(_allocation.indexer, serviceProviderSlot)); - vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 0), bytes32(tokens)); - vm.store(address(staking), bytes32(uint256(serviceProviderBaseSlot) + 1), bytes32(tokens)); - - uint256 subgraphsAllocationsSlot = 16; - bytes32 subgraphAllocationsBaseSlot = keccak256(abi.encode(_allocation.subgraphDeploymentID, subgraphsAllocationsSlot)); - vm.store(address(staking), subgraphAllocationsBaseSlot, bytes32(tokens)); - } - - function _storeMaxAllocationEpochs() internal { - uint256 slot = 13; - vm.store(address(staking), bytes32(slot), bytes32(MAX_ALLOCATION_EPOCHS) << 128); - } - - function _storeRewardsDestination(address destination) internal { - uint256 rewardsDestinationSlot = 23; - bytes32 rewardsDestinationSlotBaseSlot = keccak256(abi.encode(users.indexer, rewardsDestinationSlot)); - vm.store(address(staking), rewardsDestinationSlotBaseSlot, bytes32(uint256(uint160(destination)))); - } -} \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/allocation.t.sol b/packages/horizon/test/staking/allocation/allocation.t.sol index 83e23a81f..9e80433b3 100644 --- a/packages/horizon/test/staking/allocation/allocation.t.sol +++ b/packages/horizon/test/staking/allocation/allocation.t.sol @@ -1,41 +1,18 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; -import { HorizonStakingExtensionTest } from "./HorizonStakingExtension.t.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; -contract HorizonStakingAllocationTest is HorizonStakingExtensionTest { +contract HorizonStakingAllocationTest is HorizonStakingTest { /* * TESTS */ - function testAllocation_GetAllocation() public useAllocation { - IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); - assertEq(allocation.indexer, _allocation.indexer); - assertEq(allocation.subgraphDeploymentID, _allocation.subgraphDeploymentID); - assertEq(allocation.tokens, _allocation.tokens); - assertEq(allocation.createdAtEpoch, _allocation.createdAtEpoch); - assertEq(allocation.closedAtEpoch, _allocation.closedAtEpoch); - assertEq(allocation.collectedFees, _allocation.collectedFees); - assertEq(allocation.__DEPRECATED_effectiveAllocation, _allocation.__DEPRECATED_effectiveAllocation); - assertEq(allocation.accRewardsPerAllocatedToken, _allocation.accRewardsPerAllocatedToken); - assertEq(allocation.distributedRebates, _allocation.distributedRebates); - } - - function testAllocation_GetAllocationData() public useAllocation { - (address indexer, bytes32 subgraphDeploymentID, uint256 tokens, uint256 accRewardsPerAllocatedToken, uint256 accRewardsPending) = - staking.getAllocationData(_allocationId); - assertEq(indexer, _allocation.indexer); - assertEq(subgraphDeploymentID, _allocation.subgraphDeploymentID); - assertEq(tokens, _allocation.tokens); - assertEq(accRewardsPerAllocatedToken, _allocation.accRewardsPerAllocatedToken); - assertEq(accRewardsPending, 0); - } - - function testAllocation_GetAllocationState_Active() public useAllocation { + function testAllocation_GetAllocationState_Active(uint256 tokens) public useIndexer useAllocation(tokens) { IHorizonStakingExtension.AllocationState state = staking.getAllocationState(_allocationId); assertEq(uint16(state), uint16(IHorizonStakingExtension.AllocationState.Active)); } @@ -45,7 +22,7 @@ contract HorizonStakingAllocationTest is HorizonStakingExtensionTest { assertEq(uint16(state), uint16(IHorizonStakingExtension.AllocationState.Null)); } - function testAllocation_IsAllocation() public useAllocation { + function testAllocation_IsAllocation(uint256 tokens) public useIndexer useAllocation(tokens) { bool isAllocation = staking.isAllocation(_allocationId); assertTrue(isAllocation); } diff --git a/packages/horizon/test/staking/allocation/close.t.sol b/packages/horizon/test/staking/allocation/close.t.sol index c7c2aff68..121307056 100644 --- a/packages/horizon/test/staking/allocation/close.t.sol +++ b/packages/horizon/test/staking/allocation/close.t.sol @@ -1,54 +1,42 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; -import { HorizonStakingExtensionTest } from "./HorizonStakingExtension.t.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; import { PPMMath } from "../../../contracts/libraries/PPMMath.sol"; -contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { +contract HorizonStakingCloseAllocationTest is HorizonStakingTest { using PPMMath for uint256; + bytes32 internal constant _poi = keccak256("poi"); + /* * TESTS */ - function testCloseAllocation(uint256 tokens) public useIndexer { + function testCloseAllocation(uint256 tokens) public useIndexer useAllocation(1 ether) { tokens = bound(tokens, 1, MAX_STAKING_TOKENS); - _storeAllocation(tokens); - _storeMaxAllocationEpochs(); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, tokens, 0, 0); // Skip 15 epochs vm.roll(15); - staking.closeAllocation(_allocationId, _poi); - IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); - assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); - - // Stake should be updated with rewards - assertEq(staking.getStake(address(users.indexer)), tokens * 2 + ALLOCATIONS_REWARD_CUT); + _closeAllocation(_allocationId, _poi); } - function testCloseAllocation_WithBeneficiaryAddress(uint256 tokens) public useIndexer { + function testCloseAllocation_WithBeneficiaryAddress(uint256 tokens) public useIndexer useAllocation(1 ether) { tokens = bound(tokens, 1, MAX_STAKING_TOKENS); - _storeAllocation(tokens); - _storeMaxAllocationEpochs(); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, tokens, 0, 0); address beneficiary = makeAddr("beneficiary"); - _storeRewardsDestination(beneficiary); + _setStorage_RewardsDestination(users.indexer, beneficiary); // Skip 15 epochs vm.roll(15); - staking.closeAllocation(_allocationId, _poi); - IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); - assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); - - // Stake should be updated with rewards - assertEq(token.balanceOf(beneficiary), ALLOCATIONS_REWARD_CUT); + _closeAllocation(_allocationId, _poi); } function testCloseAllocation_RevertWhen_NotActive() public { @@ -56,43 +44,32 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { staking.closeAllocation(_allocationId, _poi); } - function testCloseAllocation_RevertWhen_NotIndexer() public useAllocation { + function testCloseAllocation_RevertWhen_NotIndexer() public useIndexer useAllocation(1 ether) { resetPrank(users.delegator); vm.expectRevert("!auth"); staking.closeAllocation(_allocationId, _poi); } - function testCloseAllocation_AfterMaxEpochs_AnyoneCanClose(uint256 tokens) public useIndexer { + function testCloseAllocation_AfterMaxEpochs_AnyoneCanClose(uint256 tokens) public useIndexer useAllocation(1 ether) { tokens = bound(tokens, 1, MAX_STAKING_TOKENS); - _storeAllocation(tokens); - _storeMaxAllocationEpochs(); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, 0); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, tokens, 0, 0); // Skip to over the max allocation epochs - vm.roll(MAX_ALLOCATION_EPOCHS + 2); + vm.roll((MAX_ALLOCATION_EPOCHS + 1)* EPOCH_LENGTH + 1); resetPrank(users.delegator); - staking.closeAllocation(_allocationId, 0x0); - IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); - assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); - - // No rewards distributed - assertEq(staking.getStake(address(users.indexer)), tokens * 2); + _closeAllocation(_allocationId, 0x0); } - function testCloseAllocation_RevertWhen_ZeroTokensNotAuthorized() public useIndexer { - _storeAllocation(0); - _storeMaxAllocationEpochs(); - - // Skip to over the max allocation epochs - vm.roll(MAX_ALLOCATION_EPOCHS + 2); + function testCloseAllocation_RevertWhen_ZeroTokensNotAuthorized() public useIndexer useAllocation(1 ether){ + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 100 ether, 0, 0); resetPrank(users.delegator); vm.expectRevert("!auth"); staking.closeAllocation(_allocationId, 0x0); } - function testCloseAllocation_WithDelegation(uint256 tokens, uint256 delegationTokens, uint32 indexingRewardCut) public useIndexer { + function testCloseAllocation_WithDelegation(uint256 tokens, uint256 delegationTokens, uint32 indexingRewardCut) public useIndexer useAllocation(1 ether) { tokens = bound(tokens, 2, MAX_STAKING_TOKENS); delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); vm.assume(indexingRewardCut <= MAX_PPM); @@ -100,21 +77,12 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingExtensionTest { uint256 legacyAllocationTokens = tokens / 2; uint256 provisionTokens = tokens - legacyAllocationTokens; - _storeAllocation(legacyAllocationTokens); - _storeMaxAllocationEpochs(); - _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); - _storeDelegationPool(delegationTokens, indexingRewardCut, 0); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); + _setStorage_DelegationPool(users.indexer, delegationTokens, indexingRewardCut, 0); // Skip 15 epochs vm.roll(15); - staking.closeAllocation(_allocationId, _poi); - IHorizonStakingExtension.Allocation memory allocation = staking.getAllocation(_allocationId); - assertEq(allocation.closedAtEpoch, epochManager.currentEpoch()); - - uint256 indexerRewardCut = ALLOCATIONS_REWARD_CUT.mulPPM(indexingRewardCut); - uint256 delegationFeeCut = ALLOCATIONS_REWARD_CUT - indexerRewardCut; - assertEq(staking.getStake(address(users.indexer)), tokens + indexerRewardCut); - assertEq(staking.getDelegationPool(users.indexer, subgraphDataServiceLegacyAddress).tokens, delegationTokens + delegationFeeCut); + _closeAllocation(_allocationId, _poi); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/allocation/collect.t.sol b/packages/horizon/test/staking/allocation/collect.t.sol index 3ea230a8b..9b8b1d9e5 100644 --- a/packages/horizon/test/staking/allocation/collect.t.sol +++ b/packages/horizon/test/staking/allocation/collect.t.sol @@ -1,75 +1,20 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; -import { HorizonStakingExtensionTest } from "./HorizonStakingExtension.t.sol"; -import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; import { ExponentialRebates } from "../../../contracts/staking/libraries/ExponentialRebates.sol"; import { PPMMath } from "../../../contracts/libraries/PPMMath.sol"; -contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { +contract HorizonStakingCollectAllocationTest is HorizonStakingTest { using PPMMath for uint256; - uint32 private alphaNumerator = 100; - uint32 private alphaDenominator = 100; - uint32 private lambdaNumerator = 60; - uint32 private lambdaDenominator = 100; - - /* - * MODIFIERS - */ - - modifier useRebateParameters() { - _storeRebateParameters(); - _; - } - - /* - * HELPERS - */ - - function _storeRebateParameters() private { - // Store alpha numerator and denominator - uint256 alphaSlot = 13; - uint256 alphaNumeratorOffset = 20; - uint256 alphaDenominatorOffset = 24; - bytes32 alphaValues = bytes32( - (uint256(alphaNumerator) << (8 * alphaNumeratorOffset)) | - (uint256(alphaDenominator) << (8 * alphaDenominatorOffset)) - ); - vm.store(address(staking), bytes32(alphaSlot), alphaValues); - - // Store lambda numerator and denominator - uint256 lambdaSlot = 25; - uint256 lambdaNumeratorOffset = 20; - uint256 lambdaDenominatorOffset = 24; - bytes32 lambdaValues = bytes32( - (uint256(lambdaNumerator) << (8 * lambdaNumeratorOffset)) | - (uint256(lambdaDenominator) << (8 * lambdaDenominatorOffset)) - ); - vm.store(address(staking), bytes32(lambdaSlot), lambdaValues); - } - - function _storeProtocolTaxAndCuration(uint32 curationPercentage, uint32 taxPercentage) private { - bytes32 slot = bytes32(uint256(13)); - uint256 curationOffset = 4; - uint256 protocolTaxOffset = 8; - bytes32 originalValue = vm.load(address(staking), slot); - - bytes32 newProtocolTaxValue = bytes32( - (uint256(originalValue) & ~((0xFFFFFFFF << (8 * curationOffset)) | (0xFFFFFFFF << (8 * protocolTaxOffset))) | - (uint256(curationPercentage) << (8 * curationOffset))) | - (uint256(taxPercentage) << (8 * protocolTaxOffset)) - ); - vm.store(address(staking), slot, newProtocolTaxValue); - } - /* * TESTS */ - function testCollectAllocation_RevertWhen_InvalidAllocationId(uint256 tokens) public useAllocation { + function testCollectAllocation_RevertWhen_InvalidAllocationId(uint256 tokens) public useIndexer useAllocation(1 ether) { vm.expectRevert("!alloc"); staking.collect(tokens, address(0)); } @@ -79,13 +24,7 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { staking.collect(tokens, _allocationId); } - function testCollectAllocation_ZeroTokens() public useAllocation { - staking.collect(0, _allocationId); - assertEq(staking.getStake(address(users.indexer)), 0); - } - function testCollect_Tokenss( - uint256 provisionTokens, uint256 allocationTokens, uint256 collectTokens, uint256 curationTokens, @@ -93,75 +32,37 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { uint32 protocolTaxPercentage, uint256 delegationTokens, uint32 queryFeeCut - ) public useRebateParameters { - provisionTokens = bound(provisionTokens, 1, MAX_STAKING_TOKENS); - allocationTokens = bound(allocationTokens, 0, MAX_STAKING_TOKENS); + ) public useIndexer useRebateParameters useAllocation(allocationTokens) { collectTokens = bound(collectTokens, 0, MAX_STAKING_TOKENS); curationTokens = bound(curationTokens, 0, MAX_STAKING_TOKENS); delegationTokens = bound(delegationTokens, 0, MAX_STAKING_TOKENS); vm.assume(curationPercentage <= MAX_PPM); vm.assume(protocolTaxPercentage <= MAX_PPM); vm.assume(queryFeeCut <= MAX_PPM); + resetPrank(users.indexer); - _storeAllocation(allocationTokens); - _storeProtocolTaxAndCuration(curationPercentage, protocolTaxPercentage); - _storeDelegationPool(delegationTokens, 0, queryFeeCut); - _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); + _setStorage_ProtocolTaxAndCuration(curationPercentage, protocolTaxPercentage); + console.log("queryFeeCut", queryFeeCut); + _setStorage_DelegationPool(users.indexer, delegationTokens, 0, queryFeeCut); curation.signal(_subgraphDeploymentID, curationTokens); resetPrank(users.gateway); approve(address(staking), collectTokens); - staking.collect(collectTokens, _allocationId); - - uint256 protocolTaxTokens = collectTokens.mulPPMRoundUp(protocolTaxPercentage); - uint256 queryFees = collectTokens - protocolTaxTokens; - - uint256 curationCutTokens = 0; - if (curationTokens > 0) { - curationCutTokens = queryFees.mulPPMRoundUp(curationPercentage); - queryFees -= curationCutTokens; - } - - uint256 newRebates = ExponentialRebates.exponentialRebates( - queryFees, - allocationTokens, - alphaNumerator, - alphaDenominator, - lambdaNumerator, - lambdaDenominator - ); - uint256 payment = newRebates > queryFees ? queryFees : newRebates; - - uint256 delegationFeeCut = 0; - if (delegationTokens > 0) { - delegationFeeCut = payment - payment.mulPPM(queryFeeCut); - payment -= delegationFeeCut; - } - - assertEq(staking.getStake(address(users.indexer)), allocationTokens + provisionTokens + payment); - assertEq(curation.curation(_subgraphDeploymentID), curationTokens + curationCutTokens); - assertEq(staking.getDelegationPool(users.indexer, subgraphDataServiceLegacyAddress).tokens, delegationTokens + delegationFeeCut); - assertEq(token.balanceOf(address(payments)), 0); + _collect(collectTokens, _allocationId); } function testCollect_WithBeneficiaryAddress( - uint256 provisionTokens, uint256 allocationTokens, uint256 collectTokens - ) public useIndexer useRebateParameters { - provisionTokens = bound(provisionTokens, 1, MAX_STAKING_TOKENS); - allocationTokens = bound(allocationTokens, 0, MAX_STAKING_TOKENS); + ) public useIndexer useRebateParameters useAllocation(allocationTokens) { collectTokens = bound(collectTokens, 0, MAX_STAKING_TOKENS); - _createProvision(subgraphDataServiceLegacyAddress, provisionTokens, 0, 0); - _storeAllocation(allocationTokens); - address beneficiary = makeAddr("beneficiary"); - _storeRewardsDestination(beneficiary); + _setStorage_RewardsDestination(users.indexer, beneficiary); resetPrank(users.gateway); approve(address(staking), collectTokens); - staking.collect(collectTokens, _allocationId); + _collect(collectTokens, _allocationId); uint256 newRebates = ExponentialRebates.exponentialRebates( collectTokens, @@ -175,4 +76,4 @@ contract HorizonStakingCollectAllocationTest is HorizonStakingExtensionTest { assertEq(token.balanceOf(beneficiary), payment); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/delegation/addToPool.t.sol b/packages/horizon/test/staking/delegation/addToPool.t.sol index 4ef0c480a..e88becbbf 100644 --- a/packages/horizon/test/staking/delegation/addToPool.t.sol +++ b/packages/horizon/test/staking/delegation/addToPool.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -27,9 +27,7 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { resetPrank(subgraphDataServiceAddress); mint(subgraphDataServiceAddress, delegationAmount); token.approve(address(staking), delegationAmount); - vm.expectEmit(address(staking)); - emit IHorizonStakingMain.TokensToDelegationPoolAdded(users.indexer, subgraphDataServiceAddress, delegationAmount); - staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(delegatedTokens, delegationAmount); @@ -46,7 +44,7 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { resetPrank(address(payments)); mint(address(payments), delegationAmount); token.approve(address(staking), delegationAmount); - staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(delegatedTokens, delegationAmount); diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 87416daf5..d5e101bca 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -30,7 +30,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { vm.startPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); undelegateAmount = bound(undelegateAmount, 1 wei, delegation.shares - 1 ether); _undelegate(users.indexer, subgraphDataServiceAddress, undelegateAmount); @@ -46,7 +46,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { vm.startPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); @@ -78,10 +78,10 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { function testDelegate_LegacySubgraphService(uint256 amount, uint256 delegationAmount) public useIndexer { amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); - _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); - _delegateLegacy(users.indexer, delegationAmount); + _delegate(users.indexer, delegationAmount); } function testDelegate_RevertWhen_InvalidPool( @@ -112,7 +112,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); resetPrank(subgraphDataServiceAddress); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index d256d8502..cc2492ba8 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -17,7 +17,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 delegationAmount ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); } @@ -31,7 +31,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); // there is a min delegation amount of 1 ether after undelegating uint256 undelegateAmount = (delegation.shares - 1 ether) / undelegateSteps; @@ -73,7 +73,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 overDelegationShares ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); overDelegationShares = bound(overDelegationShares, delegation.shares + 1, MAX_STAKING_TOKENS + 1); bytes memory expectedError = abi.encodeWithSignature( @@ -104,13 +104,13 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { function testUndelegate_LegacySubgraphService(uint256 amount, uint256 delegationAmount) public useIndexer { amount = bound(amount, 1, MAX_STAKING_TOKENS); delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); - _createProvision(subgraphDataServiceLegacyAddress, amount, 0, 0); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); - _delegateLegacy(users.indexer, delegationAmount); + _delegate(users.indexer, delegationAmount); - Delegation memory delegation = _getDelegation(subgraphDataServiceLegacyAddress); - _undelegateLegacy(users.indexer, delegation.shares); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, true); + _undelegate(users.indexer, delegation.shares); } function testUndelegate_RevertWhen_InvalidPool( @@ -125,7 +125,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); resetPrank(users.delegator); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); vm.expectRevert(abi.encodeWithSelector( IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, users.indexer, diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 7eb6db57e..fc9072898 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -17,11 +17,11 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { modifier useUndelegate(uint256 shares) { vm.stopPrank(); vm.startPrank(users.delegator); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); shares = bound(shares, 1, delegation.shares); if (shares != delegation.shares) { - DelegationPool memory pool = _getDelegationPool(subgraphDataServiceAddress); + DelegationPoolInternalTest memory pool = _getStorage_DelegationPoolInternal(users.indexer, subgraphDataServiceAddress, false); uint256 tokens = (shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 newTokensThawing = pool.tokensThawing + tokens; uint256 remainingTokens = (delegation.shares * (pool.tokens - newTokensThawing)) / pool.shares; @@ -35,37 +35,13 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { /* * HELPERS */ - - function _withdrawDelegated(address _verifier, address _newIndexer) private { - LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, _verifier, users.delegator); - ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); - - uint256 previousBalance = token.balanceOf(users.delegator); - uint256 expectedTokens = _expectedTokensFromThawRequest(thawRequest, _verifier); - staking.withdrawDelegated(users.indexer, _verifier, _newIndexer, 0, 0); - - if (_newIndexer != address(0)) { - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(_newIndexer, _verifier); - assertEq(delegatedTokens, expectedTokens); - } else { - uint256 newBalance = token.balanceOf(users.delegator); - assertEq(newBalance - previousBalance, expectedTokens); - } - } - - function _expectedTokensFromThawRequest(ThawRequest memory thawRequest, address verifier) private view returns (uint256) { - DelegationPool memory pool = _getDelegationPool(verifier); - return (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing; - } - function _setupNewIndexer(uint256 tokens) private returns(address) { - address msgSender; - (, msgSender,) = vm.readCallers(); + (, address msgSender,) = vm.readCallers(); + address newIndexer = createUser("newIndexer"); vm.startPrank(newIndexer); - token.approve(address(staking), tokens); - staking.stakeTo(newIndexer, tokens); - staking.provision(newIndexer,subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + _createProvision(newIndexer, subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + vm.startPrank(msgSender); return newIndexer; } @@ -89,7 +65,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { skip(thawRequest.thawingUntil + 1); - _withdrawDelegated(subgraphDataServiceAddress, address(0)); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); } function testWithdrawDelegation_RevertWhen_NotThawing( @@ -118,7 +94,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { // Setup new service provider address newIndexer = _setupNewIndexer(10_000_000 ether); - _withdrawDelegated(subgraphDataServiceAddress, newIndexer); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); } function testWithdrawDelegation_ZeroTokens( @@ -131,7 +107,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useUndelegate(delegationAmount) { uint256 previousBalance = token.balanceOf(users.delegator); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); // Nothing changed since thawing period haven't finished uint256 newBalance = token.balanceOf(users.delegator); @@ -151,7 +127,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { address newIndexer = _setupNewIndexer(10_000_000 ether); uint256 previousBalance = token.balanceOf(users.delegator); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); uint256 newBalance = token.balanceOf(users.delegator); assertEq(newBalance, previousBalance); @@ -162,19 +138,19 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { function testWithdrawDelegation_LegacySubgraphService(uint256 delegationAmount) public useIndexer { delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); - _createProvision(subgraphDataServiceLegacyAddress, 10_000_000 ether, 0, MAX_THAWING_PERIOD); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 10_000_000 ether, 0, MAX_THAWING_PERIOD); resetPrank(users.delegator); - _delegateLegacy(users.indexer, delegationAmount); - Delegation memory delegation = _getDelegation(subgraphDataServiceLegacyAddress); - _undelegateLegacy(users.indexer, delegation.shares); + _delegate(users.indexer, delegationAmount); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, true); + _undelegate(users.indexer, delegation.shares); LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceLegacyAddress, users.delegator); ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); skip(thawRequest.thawingUntil + 1); - _withdrawDelegated(subgraphDataServiceLegacyAddress, address(0)); + _withdrawDelegated(users.indexer, address(0)); } function testWithdrawDelegation_RevertWhen_InvalidPool( @@ -184,7 +160,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); - Delegation memory delegation = _getDelegation(subgraphDataServiceAddress); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); skip(MAX_THAWING_PERIOD + 1); diff --git a/packages/horizon/test/staking/governance/governance.t.sol b/packages/horizon/test/staking/governance/governance.t.sol index 932e053c4..401828a3e 100644 --- a/packages/horizon/test/staking/governance/governance.t.sol +++ b/packages/horizon/test/staking/governance/governance.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -21,8 +21,7 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { */ function testGovernance_SetAllowedLockedVerifier() public useGovernor { - staking.setAllowedLockedVerifier(subgraphDataServiceAddress, true); - assertTrue(staking.isAllowedLockedVerifier(subgraphDataServiceAddress)); + _setAllowedLockedVerifier(subgraphDataServiceAddress, true); } function testGovernance_RevertWhen_SetAllowedLockedVerifier_NotGovernor() public useIndexer { @@ -32,8 +31,7 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { } function testGovernance_SetDelgationSlashingEnabled() public useGovernor { - staking.setDelegationSlashingEnabled(); - assertTrue(staking.isDelegationSlashingEnabled()); + _setDelegationSlashingEnabled(); } function testGovernance_SetDelgationSlashing_NotGovernor() public useIndexer { @@ -43,11 +41,10 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { } function testGovernance_ClearThawingPeriod(uint32 thawingPeriod) public useGovernor { - vm.store(address(staking), bytes32(uint256(13)), bytes32(uint256(thawingPeriod))); - assertEq(staking.__DEPRECATED_getThawingPeriod(), thawingPeriod); + // simulate previous thawing period + _setStorage_DeprecatedThawingPeriod(thawingPeriod); - staking.clearThawingPeriod(); - assertEq(staking.__DEPRECATED_getThawingPeriod(), 0); + _clearThawingPeriod(); } function testGovernance_ClearThawingPeriod_NotGovernor() public useIndexer { @@ -57,8 +54,7 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { } function testGovernance__SetMaxThawingPeriod(uint64 maxThawingPeriod) public useGovernor { - staking.setMaxThawingPeriod(maxThawingPeriod); - assertEq(staking.getMaxThawingPeriod(), maxThawingPeriod); + _setMaxThawingPeriod(maxThawingPeriod); } function testGovernance__SetMaxThawingPeriod_NotGovernor() public useIndexer { @@ -68,10 +64,7 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { } function testGovernance_SetCounterpartStakingAddress(address counterpartStakingAddress) public useGovernor { - staking.setCounterpartStakingAddress(counterpartStakingAddress); - bytes32 storedValue = vm.load(address(staking), bytes32(uint256(24))); - address storedCounterpartStakingAddress = address(uint160(uint256(storedValue))); - assertEq(storedCounterpartStakingAddress, counterpartStakingAddress); + _setCounterpartStakingAddress(counterpartStakingAddress); } function testGovernance_RevertWhen_SetCounterpartStakingAddress_NotGovernor( diff --git a/packages/horizon/test/staking/operator/locked.t.sol b/packages/horizon/test/staking/operator/locked.t.sol index e6eb8038d..706b47a07 100644 --- a/packages/horizon/test/staking/operator/locked.t.sol +++ b/packages/horizon/test/staking/operator/locked.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -12,8 +12,7 @@ contract HorizonStakingOperatorLockedTest is HorizonStakingTest { */ function testOperatorLocked_Set() public useIndexer useLockedVerifier(subgraphDataServiceAddress) { - staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); - assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + _setOperatorLocked(users.operator, subgraphDataServiceAddress, true); } function testOperatorLocked_RevertWhen_VerifierNotAllowed() public useIndexer { @@ -29,7 +28,6 @@ contract HorizonStakingOperatorLockedTest is HorizonStakingTest { } function testOperatorLocked_SetLegacySubgraphService() public useIndexer useLockedVerifier(subgraphDataServiceLegacyAddress) { - staking.setOperatorLocked(users.operator, subgraphDataServiceLegacyAddress, true); - assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceLegacyAddress)); + _setOperatorLocked(users.operator, subgraphDataServiceLegacyAddress, true); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/operator/operator.t.sol b/packages/horizon/test/staking/operator/operator.t.sol index af06e0ef5..5d509ba68 100644 --- a/packages/horizon/test/staking/operator/operator.t.sol +++ b/packages/horizon/test/staking/operator/operator.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -11,8 +11,8 @@ contract HorizonStakingOperatorTest is HorizonStakingTest { * TESTS */ - function testOperator_SetOperator() public useOperator { - assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + function testOperator_SetOperator() public useIndexer { + _setOperator(users.operator, subgraphDataServiceAddress, true); } function testOperator_RevertWhen_CallerIsServiceProvider() public useIndexer { @@ -22,10 +22,7 @@ contract HorizonStakingOperatorTest is HorizonStakingTest { } function testOperator_RemoveOperator() public useIndexer { - staking.setOperator(users.operator, subgraphDataServiceAddress, true); - assertTrue(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); - - staking.setOperator(users.operator, subgraphDataServiceAddress, false); - assertFalse(staking.isAuthorized(users.operator, users.indexer, subgraphDataServiceAddress)); + _setOperator(users.operator, subgraphDataServiceAddress, true); + _setOperator(users.operator, subgraphDataServiceAddress, false); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index fbb9d0fc4..6d03c3f6e 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDeprovisionTest is HorizonStakingTest { - /* * TESTS */ @@ -14,52 +13,65 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { function testDeprovision_AllRequests( uint256 amount, uint32 maxVerifierCut, - uint64 thawingPeriod - ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + uint64 thawingPeriod, + uint256 thawCount, + uint256 deprovisionCount + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + thawCount = bound(thawCount, 1, MAX_THAW_REQUESTS); + deprovisionCount = bound(deprovisionCount, 0, thawCount); + vm.assume(amount >= thawCount); // ensure the provision has at least 1 token for each thaw step + uint256 individualThawAmount = amount / thawCount; + + for (uint i = 0; i < thawCount; i++) { + _thaw(users.indexer, subgraphDataServiceAddress, individualThawAmount); + } + skip(thawingPeriod + 1); - // nThawRequests == 0 removes all thaw requests - _deprovision(0); - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, amount); + _deprovision(users.indexer, subgraphDataServiceAddress, deprovisionCount); } - function testDeprovision_FirstRequestOnly( + function testDeprovision_ThawedRequests( uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod, - uint256 thawAmount + uint256 thawCount ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - vm.assume(amount > 1); - thawAmount = bound(thawAmount, 2, amount); - uint256 thawAmount1 = thawAmount / 2; - _createThawRequest(thawAmount1); - _createThawRequest(thawAmount - thawAmount1); + thawCount = bound(thawCount, 2, MAX_THAW_REQUESTS); + vm.assume(amount >= thawCount); // ensure the provision has at least 1 token for each thaw step + uint256 individualThawAmount = amount / thawCount; + + for (uint i = 0; i < thawCount / 2; i++) { + _thaw(users.indexer, subgraphDataServiceAddress, individualThawAmount); + } skip(thawingPeriod + 1); - _deprovision(1); - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, thawAmount1); + for (uint i = 0; i < thawCount / 2; i++) { + _thaw(users.indexer, subgraphDataServiceAddress, individualThawAmount); + } + + _deprovision(users.indexer, subgraphDataServiceAddress, 0); } function testDeprovision_OperatorMovingTokens( uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod - ) public useOperator useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useOperator { + _thaw(users.indexer, subgraphDataServiceAddress, amount); skip(thawingPeriod + 1); - _deprovision(0); - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, amount); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); } function testDeprovision_RevertWhen_OperatorNotAuthorized( uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod - ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + _thaw(users.indexer, subgraphDataServiceAddress, amount); + vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingNotAuthorized(address,address,address)", @@ -68,8 +80,9 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { subgraphDataServiceAddress ); vm.expectRevert(expectedError); - _deprovision(0); + staking.deprovision(users.indexer, subgraphDataServiceAddress, 0); } + function testDeprovision_RevertWhen_NoThawingTokens( uint256 amount, uint32 maxVerifierCut, @@ -77,17 +90,18 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - _deprovision(0); + staking.deprovision(users.indexer, subgraphDataServiceAddress, 0); } function testDeprovision_StillThawing( uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod - ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useThawRequest(amount) { + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { vm.assume(thawingPeriod > 0); - _deprovision(0); - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, 0); + + _thaw(users.indexer, subgraphDataServiceAddress, amount); + + _deprovision(users.indexer, subgraphDataServiceAddress, 0); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/provision/locked.t.sol b/packages/horizon/test/staking/provision/locked.t.sol index 642ba9a10..a8adfc774 100644 --- a/packages/horizon/test/staking/provision/locked.t.sol +++ b/packages/horizon/test/staking/provision/locked.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -17,10 +17,10 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(provisionTokens, 0); - staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + _setOperatorLocked(users.operator, subgraphDataServiceAddress, true); vm.startPrank(users.operator); - staking.provisionLocked( + _provisionLocked( users.indexer, subgraphDataServiceAddress, amount, @@ -39,11 +39,11 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { assertEq(provisionTokens, 0); // Set operator - staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + _setOperatorLocked(users.operator, subgraphDataServiceAddress, true); // Disable locked verifier vm.startPrank(users.governor); - staking.setAllowedLockedVerifier(subgraphDataServiceAddress, false); + _setAllowedLockedVerifier(subgraphDataServiceAddress, false); vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature("HorizonStakingVerifierNotAllowed(address)", subgraphDataServiceAddress); diff --git a/packages/horizon/test/staking/provision/parameters.t.sol b/packages/horizon/test/staking/provision/parameters.t.sol index 298059a7a..8171f95b4 100644 --- a/packages/horizon/test/staking/provision/parameters.t.sol +++ b/packages/horizon/test/staking/provision/parameters.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -16,20 +16,7 @@ contract HorizonStakingProvisionParametersTest is HorizonStakingTest { uint32 maxVerifierCut, uint64 thawingPeriod ) public useIndexer useProvision(amount, 0, 0) { - vm.assume(maxVerifierCut != 0); - vm.assume(thawingPeriod != 0); - vm.expectEmit(); - emit IHorizonStakingMain.ProvisionParametersStaged( - users.indexer, - subgraphDataServiceAddress, - maxVerifierCut, - thawingPeriod - ); - staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); - - Provision memory prov = staking.getProvision(users.indexer, subgraphDataServiceAddress); - assertEq(prov.maxVerifierCutPending, maxVerifierCut); - assertEq(prov.thawingPeriodPending, thawingPeriod); + _setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); } function test_ProvisionParametersSet_RevertWhen_ProvisionNotExists( @@ -78,27 +65,10 @@ contract HorizonStakingProvisionParametersTest is HorizonStakingTest { uint32 maxVerifierCut, uint64 thawingPeriod ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - Provision memory prov = staking.getProvision(users.indexer, subgraphDataServiceAddress); - - staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + _setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); vm.startPrank(subgraphDataServiceAddress); - - if (maxVerifierCut != prov.maxVerifierCut || thawingPeriod != prov.thawingPeriod) { - vm.expectEmit(); - emit IHorizonStakingMain.ProvisionParametersSet( - users.indexer, - subgraphDataServiceAddress, - maxVerifierCut, - thawingPeriod - ); - } - staking.acceptProvisionParameters(users.indexer); + _acceptProvisionParameters(users.indexer); vm.stopPrank(); - - assertEq(prov.maxVerifierCut, maxVerifierCut); - assertEq(prov.maxVerifierCutPending, maxVerifierCut); - assertEq(prov.thawingPeriod, thawingPeriod); - assertEq(prov.thawingPeriodPending, thawingPeriod); } } diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index 3394460fb..50dc12057 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -10,13 +10,12 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { * TESTS */ - function testProvision_Create( - uint256 amount, - uint32 maxVerifierCut, - uint64 thawingPeriod - ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(provisionTokens, amount); + function testProvision_Create(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) public useIndexer { + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + maxVerifierCut = uint32(bound(maxVerifierCut, 0, MAX_MAX_VERIFIER_CUT)); + thawingPeriod = uint32(bound(thawingPeriod, 0, MAX_THAWING_PERIOD)); + + _createProvision(users.indexer, subgraphDataServiceAddress, tokens, maxVerifierCut, thawingPeriod); } function testProvision_RevertWhen_ZeroTokens() public useIndexer useStake(1000 ether) { @@ -75,7 +74,7 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { resetPrank(users.indexer); token.approve(address(staking), amount / 2); - staking.stake(amount / 2); + _stake(amount / 2); bytes memory expectedError = abi.encodeWithSignature("HorizonStakingProvisionAlreadyExists()"); vm.expectRevert(expectedError); @@ -87,18 +86,12 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { uint32 maxVerifierCut, uint64 thawingPeriod, uint256 tokensToAdd - ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { - tokensToAdd = bound(tokensToAdd, 1, type(uint256).max - amount); - // Set operator - staking.setOperator(users.operator, subgraphDataServiceAddress, true); + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) useOperator { + tokensToAdd = bound(tokensToAdd, 1, MAX_STAKING_TOKENS); // Add more tokens to the provision - vm.startPrank(users.operator); _stakeTo(users.indexer, tokensToAdd); - staking.addToProvision(users.indexer, subgraphDataServiceAddress, tokensToAdd); - - uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(provisionTokens, amount + tokensToAdd); + _addToProvision(users.indexer, subgraphDataServiceAddress, tokensToAdd); } function testProvision_RevertWhen_OperatorNotAuthorized( diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 5d7ed8068..6fd170e4b 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -1,26 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingReprovisionTest is HorizonStakingTest { - /* * VARIABLES */ address private newDataService = makeAddr("newDataService"); - /* - * HELPERS - */ - - function _reprovision(uint256 tokens, uint256 nThawRequests) private { - staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, tokens, nThawRequests); - } - /* * TESTS */ @@ -28,62 +19,62 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { function testReprovision_MovingTokens( uint64 thawingPeriod, uint256 provisionAmount - ) - public - useIndexer - useProvision(provisionAmount, 0, thawingPeriod) - useThawRequest(provisionAmount) - { + ) public useIndexer useProvision(provisionAmount, 0, thawingPeriod) { + _thaw(users.indexer, subgraphDataServiceAddress, provisionAmount); skip(thawingPeriod + 1); - _createProvision(newDataService, 1 ether, 0, thawingPeriod); + _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); + + _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); + } - // nThawRequests == 0 reprovisions all thaw requests - _reprovision(provisionAmount, 0); - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, 0 ether); + function testReprovision_TokensOverThawingTokens() public useIndexer { + uint64 thawingPeriod = 1 days; - uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, newDataService); - assertEq(provisionTokens, provisionAmount + 1 ether); + // create provision A, thaw 10 ether, skip time so they are fully thawed + _createProvision(users.indexer, subgraphDataServiceAddress, 100 ether, 0, thawingPeriod); + _thaw(users.indexer, subgraphDataServiceAddress, 10 ether); + skip(thawingPeriod + 1); + + // create provision B + _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); + + // reprovision 100 ether from A to B + // this should revert because there are only 10 ether that thawed and the service provider + // doesn't have additional idle stake to cover the difference + vm.expectRevert(); + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 100 ether, 0); + + // now add some idle stake and try again, it should not revert + _stake(100 ether); + _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 100 ether, 0); } function testReprovision_OperatorMovingTokens( uint64 thawingPeriod, uint256 provisionAmount - ) - public - useOperator - useProvision(provisionAmount, 0, thawingPeriod) - useThawRequest(provisionAmount) - { + ) public useOperator useProvision(provisionAmount, 0, thawingPeriod) { + _thaw(users.indexer, subgraphDataServiceAddress, provisionAmount); skip(thawingPeriod + 1); // Switch to indexer to set operator for new data service vm.startPrank(users.indexer); - staking.setOperator(users.operator, newDataService, true); - + _setOperator(users.operator, newDataService, true); + // Switch back to operator vm.startPrank(users.operator); - _createProvision(newDataService, 1 ether, 0, thawingPeriod); - _reprovision(provisionAmount, 0); - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, 0 ether); - - uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, newDataService); - assertEq(provisionTokens, provisionAmount + 1 ether); + _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); + _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); } function testReprovision_RevertWhen_OperatorNotAuthorizedForNewDataService( uint256 provisionAmount - ) - public - useOperator - useProvision(provisionAmount, 0, 0) - useThawRequest(provisionAmount) - { + ) public useOperator useProvision(provisionAmount, 0, 0) { + _thaw(users.indexer, subgraphDataServiceAddress, provisionAmount); + // Switch to indexer to create new provision vm.startPrank(users.indexer); - _createProvision(newDataService, 1 ether, 0, 0); + _createProvision(users.indexer, newDataService, 1 ether, 0, 0); // Switch back to operator vm.startPrank(users.operator); @@ -94,29 +85,23 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { newDataService ); vm.expectRevert(expectedError); - _reprovision(provisionAmount, 0); + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); } - function testReprovision_RevertWhen_NoThawingTokens( - uint256 amount - ) public useIndexer useProvision(amount, 0, 0) { + function testReprovision_RevertWhen_NoThawingTokens(uint256 amount) public useIndexer useProvision(amount, 0, 0) { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - _reprovision(amount, 0); + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, amount, 0); } function testReprovision_RevertWhen_StillThawing( uint64 thawingPeriod, uint256 provisionAmount - ) - public - useIndexer - useProvision(provisionAmount, 0, thawingPeriod) - useThawRequest(provisionAmount) - { + ) public useIndexer useProvision(provisionAmount, 0, thawingPeriod) { vm.assume(thawingPeriod > 0); + _thaw(users.indexer, subgraphDataServiceAddress, provisionAmount); - _createProvision(newDataService, 1 ether, 0, thawingPeriod); + _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientIdleStake(uint256,uint256)", @@ -124,6 +109,6 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { 0 ); vm.expectRevert(expectedError); - _reprovision(provisionAmount, 0); + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/thaw/thaw.t.sol b/packages/horizon/test/staking/provision/thaw.t.sol similarity index 58% rename from packages/horizon/test/staking/thaw/thaw.t.sol rename to packages/horizon/test/staking/provision/thaw.t.sol index 2ed99682f..bb0b3409d 100644 --- a/packages/horizon/test/staking/thaw/thaw.t.sol +++ b/packages/horizon/test/staking/provision/thaw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -7,7 +7,6 @@ import { IHorizonStakingTypes } from "../../../contracts/interfaces/internal/IHo import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingThawTest is HorizonStakingTest { - /* * TESTS */ @@ -18,48 +17,29 @@ contract HorizonStakingThawTest is HorizonStakingTest { uint256 thawAmount ) public useIndexer useProvision(amount, 0, thawingPeriod) { thawAmount = bound(thawAmount, 1, amount); - bytes32 expectedThawRequestId = keccak256( - abi.encodePacked(users.indexer, subgraphDataServiceAddress, users.indexer, uint256(0)) - ); - bytes32 thawRequestId = _createThawRequest(thawAmount); - assertEq(thawRequestId, expectedThawRequestId); - ThawRequest memory thawRequest = staking.getThawRequest(expectedThawRequestId); - assertEq(thawRequest.shares, thawAmount); - assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); } function testThaw_MultipleRequests( uint256 amount, uint64 thawingPeriod, - uint256 thawAmount, - uint256 thawAmount2 + uint256 thawCount ) public useIndexer useProvision(amount, 0, thawingPeriod) { - vm.assume(amount > 1); - thawAmount = bound(thawAmount, 1, amount - 1); - thawAmount2 = bound(thawAmount2, 1, amount - thawAmount); - bytes32 thawRequestId = _createThawRequest(thawAmount); - bytes32 thawRequestId2 = _createThawRequest(thawAmount2); - - ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); - assertEq(thawRequest.shares, thawAmount); - assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); - assertEq(thawRequest.next, thawRequestId2); + thawCount = bound(thawCount, 1, MAX_THAW_REQUESTS); + vm.assume(amount >= thawCount); // ensure the provision has at least 1 token for each thaw step + uint256 individualThawAmount = amount / thawCount; - ThawRequest memory thawRequest2 = staking.getThawRequest(thawRequestId2); - assertEq(thawRequest2.shares, thawAmount2); - assertEq(thawRequest2.thawingUntil, block.timestamp + thawingPeriod); + for (uint i = 0; i < thawCount; i++) { + _thaw(users.indexer, subgraphDataServiceAddress, individualThawAmount); + } } function testThaw_OperatorCanStartThawing( uint256 amount, uint64 thawingPeriod - ) public useOperator useProvision(amount, 0, thawingPeriod) { - bytes32 thawRequestId = _createThawRequest(amount); - - ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); - assertEq(thawRequest.shares, amount); - assertEq(thawRequest.thawingUntil, block.timestamp + thawingPeriod); + ) public useIndexer useProvision(amount, 0, thawingPeriod) useOperator { + _thaw(users.indexer, subgraphDataServiceAddress, amount); } function testThaw_RevertWhen_OperatorNotAuthorized( @@ -74,7 +54,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { subgraphDataServiceAddress ); vm.expectRevert(expectedError); - _createThawRequest(amount); + staking.thaw(users.indexer, subgraphDataServiceAddress, amount); } function testThaw_RevertWhen_InsufficientTokensAvailable( @@ -89,7 +69,7 @@ contract HorizonStakingThawTest is HorizonStakingTest { thawAmount ); vm.expectRevert(expectedError); - _createThawRequest(thawAmount); + staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); } function testThaw_RevertWhen_OverMaxThawRequests( @@ -100,13 +80,13 @@ contract HorizonStakingThawTest is HorizonStakingTest { vm.assume(amount >= MAX_THAW_REQUESTS + 1); thawAmount = bound(thawAmount, 1, amount / (MAX_THAW_REQUESTS + 1)); - for (uint256 i = 0; i < 100; i++) { - _createThawRequest(thawAmount); + for (uint256 i = 0; i < MAX_THAW_REQUESTS; i++) { + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); } bytes memory expectedError = abi.encodeWithSignature("HorizonStakingTooManyThawRequests()"); vm.expectRevert(expectedError); - _createThawRequest(thawAmount); + staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); } function testThaw_RevertWhen_ThawingZeroTokens( @@ -116,6 +96,6 @@ contract HorizonStakingThawTest is HorizonStakingTest { uint256 thawAmount = 0 ether; bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInvalidZeroTokens()"); vm.expectRevert(expectedError); - _createThawRequest(thawAmount); + staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); } } diff --git a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol index 2d32fa9e2..63578791a 100644 --- a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol +++ b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -25,7 +25,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { assertEq(sp.tokensStaked, amount); assertEq(sp.tokensProvisioned, amount); - staking.setOperator(users.operator, subgraphDataServiceAddress, true); + _setOperator(users.operator, subgraphDataServiceAddress, true); resetPrank(users.operator); _stakeTo(users.indexer, operatorAmount); sp = staking.getServiceProvider(users.indexer); @@ -40,7 +40,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { vm.assume(paymentTypeInput < 3); IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes(paymentTypeInput); feeCut = bound(feeCut, 0, MAX_PPM); - _setDelegationFeeCut(paymentType, feeCut); + _setDelegationFeeCut(users.indexer, subgraphDataServiceAddress, paymentType, feeCut); } function testServiceProvider_GetProvision( @@ -60,7 +60,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { assertEq(p.maxVerifierCutPending, maxVerifierCut); assertEq(p.thawingPeriodPending, thawingPeriod); - staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); p = staking.getProvision(users.indexer, subgraphDataServiceAddress); assertEq(p.tokensThawing, thawAmount); } @@ -75,7 +75,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { uint256 tokensAvailable = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, 0); assertEq(tokensAvailable, amount); - staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); tokensAvailable = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, 0); assertEq(tokensAvailable, amount - thawAmount); } @@ -106,9 +106,9 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) { assertTrue(staking.hasStake(users.indexer)); - _createThawRequest(amount); + _thaw(users.indexer, subgraphDataServiceAddress, amount); skip(MAX_THAWING_PERIOD + 1); - _deprovision(0); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); staking.unstake(amount); assertFalse(staking.hasStake(users.indexer)); @@ -119,12 +119,12 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) { assertEq(staking.getIndexerStakedTokens(users.indexer), amount); - _createThawRequest(amount); + _thaw(users.indexer, subgraphDataServiceAddress, amount); // Does not discount thawing tokens assertEq(staking.getIndexerStakedTokens(users.indexer), amount); skip(MAX_THAWING_PERIOD + 1); - _deprovision(0); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); // Does not discount thawing tokens assertEq(staking.getIndexerStakedTokens(users.indexer), amount); diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index b68794604..bf1f2fb1e 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -8,15 +8,6 @@ import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHor import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingSlashTest is HorizonStakingTest { - - /* - * MODIFIERS - */ - - /* - * HELPERS - */ - /* * TESTS */ diff --git a/packages/horizon/test/staking/stake/stake.t.sol b/packages/horizon/test/staking/stake/stake.t.sol index 9c1c69ad9..55474245c 100644 --- a/packages/horizon/test/staking/stake/stake.t.sol +++ b/packages/horizon/test/staking/stake/stake.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -11,8 +11,9 @@ contract HorizonStakingStakeTest is HorizonStakingTest { * TESTS */ - function testStake_Tokens(uint256 amount) public useIndexer useStake(amount) { - assertTrue(staking.getStake(address(users.indexer)) == amount); + function testStake_Tokens(uint256 amount) public useIndexer { + amount = bound(amount, 1, MAX_STAKING_TOKENS); + _stake(amount); } function testStake_RevertWhen_ZeroTokens() public useIndexer { @@ -21,8 +22,9 @@ contract HorizonStakingStakeTest is HorizonStakingTest { staking.stake(0); } - function testStakeTo_Tokens(uint256 amount) public useOperator useStakeTo(users.indexer, amount) { - assertTrue(staking.getStake(address(users.indexer)) == amount); + function testStakeTo_Tokens(uint256 amount) public useOperator { + amount = bound(amount, 1, MAX_STAKING_TOKENS); + _stakeTo(users.indexer, amount); } function testStakeTo_RevertWhen_ZeroTokens() public useOperator { diff --git a/packages/horizon/test/staking/stake/unstake.t.sol b/packages/horizon/test/staking/stake/unstake.t.sol index c5d44a3fb..13ea92e00 100644 --- a/packages/horizon/test/staking/stake/unstake.t.sol +++ b/packages/horizon/test/staking/stake/unstake.t.sol @@ -1,65 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; -import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; -import { MathUtils } from "../../../contracts/libraries/MathUtils.sol"; - import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingUnstakeTest is HorizonStakingTest { - - function _unstakeTokens(uint256 _tokens) private { - uint256 previousIndexerTokens = token.balanceOf(users.indexer); - uint256 previousIndexerIdleStake = staking.getIdleStake(users.indexer); - - vm.expectEmit(address(staking)); - emit IHorizonStakingMain.StakeWithdrawn(users.indexer, _tokens); - staking.unstake(_tokens); - - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, previousIndexerIdleStake - _tokens); - - uint256 newIndexerBalance = token.balanceOf(users.indexer); - assertEq(newIndexerBalance - previousIndexerTokens, _tokens); - } - - function _unstakeDuringLockingPeriod( - uint256 _tokens, - uint256 _tokensStillThawing, - uint256 _tokensToWithdraw, - uint32 _oldLockingPeriod - ) private { - uint256 previousIndexerTokens = token.balanceOf(users.indexer); - uint256 previousIndexerIdleStake = staking.getIdleStake(users.indexer); - - vm.expectEmit(address(staking)); - uint256 lockingPeriod = block.number + THAWING_PERIOD_IN_BLOCKS; - if (_tokensStillThawing > 0) { - lockingPeriod = block.number + MathUtils.weightedAverageRoundingUp( - MathUtils.diffOrZero(_oldLockingPeriod, block.number), - _tokensStillThawing, - THAWING_PERIOD_IN_BLOCKS, - _tokens - ); - } - emit IHorizonStakingMain.StakeLocked(users.indexer, _tokens + _tokensStillThawing, lockingPeriod); - staking.unstake(_tokens); - - uint256 idleStake = staking.getIdleStake(users.indexer); - assertEq(idleStake, previousIndexerIdleStake - _tokens); - - uint256 newIndexerBalance = token.balanceOf(users.indexer); - assertEq(newIndexerBalance - previousIndexerTokens, _tokensToWithdraw); - } - - function _storeDeprecatedThawingPeriod(uint32 _thawingPeriod) private { - uint256 slot = 13; - bytes32 value = bytes32(uint256(_thawingPeriod)); - vm.store(address(staking), bytes32(slot), value); - } - /* * TESTS */ @@ -69,44 +15,60 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { uint256 tokensToUnstake, uint32 maxVerifierCut, uint64 thawingPeriod - ) - public - useIndexer - useProvision(tokens, maxVerifierCut, thawingPeriod) - { + ) public useIndexer useProvision(tokens, maxVerifierCut, thawingPeriod) { tokensToUnstake = bound(tokensToUnstake, 1, tokens); - _createThawRequest(tokens); + + // thaw, wait and deprovision + _thaw(users.indexer, subgraphDataServiceAddress, tokens); skip(thawingPeriod + 1); - _deprovision(0); - _unstakeTokens(tokensToUnstake); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); + + _unstake(tokensToUnstake); + } + + function testUnstake_LockingPeriodGreaterThanZero_NoThawing( + uint256 tokens, + uint256 tokensToUnstake, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(tokens, maxVerifierCut, thawingPeriod) { + tokensToUnstake = bound(tokensToUnstake, 1, tokens); + + // simulate transition period + _setStorage_DeprecatedThawingPeriod(THAWING_PERIOD_IN_BLOCKS); + + // thaw, wait and deprovision + _thaw(users.indexer, subgraphDataServiceAddress, tokens); + skip(thawingPeriod + 1); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); + + // unstake + _unstake(tokensToUnstake); } function testUnstake_LockingPeriodGreaterThanZero_TokensDoneThawing( uint256 tokens, uint256 tokensToUnstake, uint256 tokensLocked - ) - public - useIndexer - { + ) public useIndexer { // bounds tokens = bound(tokens, 1, MAX_STAKING_TOKENS); tokensToUnstake = bound(tokensToUnstake, 1, tokens); tokensLocked = bound(tokensLocked, 1, MAX_STAKING_TOKENS); - // vm.store to simulate locked tokens with past locking period - _storeDeprecatedThawingPeriod(THAWING_PERIOD_IN_BLOCKS); + // simulate locked tokens with past locking period + _setStorage_DeprecatedThawingPeriod(THAWING_PERIOD_IN_BLOCKS); token.transfer(address(staking), tokensLocked); - _storeServiceProvider(users.indexer, tokensLocked, 0, tokensLocked, block.number, 0); + _setStorage_ServiceProvider(users.indexer, tokensLocked, 0, tokensLocked, block.number, 0); - // create provision, thaw request and deprovision - _createProvision(subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); - _createThawRequest(tokens); + // create provision, thaw and deprovision + _createProvision(users.indexer, subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + _thaw(users.indexer, subgraphDataServiceAddress, tokens); skip(MAX_THAWING_PERIOD + 1); - _deprovision(0); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); // unstake - _unstakeDuringLockingPeriod(tokensToUnstake, 0, tokensLocked, 0); + _unstake(tokensToUnstake); } function testUnstake_LockingPeriodGreaterThanZero_TokensStillThawing( @@ -114,10 +76,7 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { uint256 tokensToUnstake, uint256 tokensThawing, uint32 tokensThawingUntilBlock - ) - public - useIndexer - { + ) public useIndexer { // bounds tokens = bound(tokens, 1, MAX_STAKING_TOKENS); tokensToUnstake = bound(tokensToUnstake, 1, tokens); @@ -125,19 +84,19 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { vm.assume(tokensThawingUntilBlock > block.number); vm.assume(tokensThawingUntilBlock < block.number + THAWING_PERIOD_IN_BLOCKS); - // vm.store to simulate locked tokens still thawing - _storeDeprecatedThawingPeriod(THAWING_PERIOD_IN_BLOCKS); + // simulate locked tokens still thawing + _setStorage_DeprecatedThawingPeriod(THAWING_PERIOD_IN_BLOCKS); token.transfer(address(staking), tokensThawing); - _storeServiceProvider(users.indexer, tokensThawing, 0, tokensThawing, tokensThawingUntilBlock, 0); + _setStorage_ServiceProvider(users.indexer, tokensThawing, 0, tokensThawing, tokensThawingUntilBlock, 0); - // create provision, thaw request and deprovision - _createProvision(subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); - _createThawRequest(tokens); + // create provision, thaw and deprovision + _createProvision(users.indexer, subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + _thaw(users.indexer, subgraphDataServiceAddress, tokens); skip(MAX_THAWING_PERIOD + 1); - _deprovision(0); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); // unstake - _unstakeDuringLockingPeriod(tokensToUnstake, tokensThawing, 0, tokensThawingUntilBlock); + _unstake(tokensToUnstake); } function testUnstake_RevertWhen_ZeroTokens( @@ -159,11 +118,7 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod - ) - public - useIndexer - useProvision(amount, maxVerifierCut, thawingPeriod) - { + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingInsufficientIdleStake(uint256,uint256)", amount, @@ -177,12 +132,8 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod - ) - public - useIndexer - useProvision(amount, maxVerifierCut, thawingPeriod) - useThawRequest(amount) - { + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + _thaw(users.indexer, subgraphDataServiceAddress, amount); skip(thawingPeriod + 1); bytes memory expectedError = abi.encodeWithSignature( @@ -193,4 +144,4 @@ contract HorizonStakingUnstakeTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.unstake(amount); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/stake/withdraw.t.sol b/packages/horizon/test/staking/stake/withdraw.t.sol index 73a96b542..b28dea022 100644 --- a/packages/horizon/test/staking/stake/withdraw.t.sol +++ b/packages/horizon/test/staking/stake/withdraw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -8,52 +8,48 @@ import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHor import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingWithdrawTest is HorizonStakingTest { - - /* - * HELPERS - */ - - function _withdrawLockedTokens(uint256 tokens) private { - uint256 previousIndexerTokens = token.balanceOf(users.indexer); - vm.expectEmit(address(staking)); - emit IHorizonStakingMain.StakeWithdrawn(users.indexer, tokens); - staking.withdraw(); - uint256 newIndexerBalance = token.balanceOf(users.indexer); - assertEq(newIndexerBalance - previousIndexerTokens, tokens); - } - /* * TESTS */ function testWithdraw_Tokens(uint256 tokens, uint256 tokensLocked) public useIndexer { - vm.assume(tokens > 0); + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); tokensLocked = bound(tokensLocked, 1, tokens); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); - _storeServiceProvider(users.indexer, tokens, 0, tokensLocked, block.timestamp, 0); - _withdrawLockedTokens(tokensLocked); + + // simulate locked tokens ready to withdraw + token.transfer(address(staking), tokens); + _setStorage_ServiceProvider(users.indexer, tokens, 0, tokensLocked, block.number, 0); + + _createProvision(users.indexer, subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + + _withdraw(); } function testWithdraw_RevertWhen_ZeroTokens(uint256 tokens) public useIndexer { - vm.assume(tokens > 0); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); - _storeServiceProvider(users.indexer, tokens, 0, 0, block.timestamp, 0); - vm.expectRevert(abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidZeroTokens.selector - )); + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); + + // simulate zero locked tokens + token.transfer(address(staking), tokens); + _setStorage_ServiceProvider(users.indexer, tokens, 0, 0, 0, 0); + + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); + + vm.expectRevert(abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingInvalidZeroTokens.selector)); staking.withdraw(); } function testWithdraw_RevertWhen_StillThawing(uint256 tokens, uint256 tokensLocked) public useIndexer { - vm.assume(tokens > 0); + tokens = bound(tokens, 1, MAX_STAKING_TOKENS); tokensLocked = bound(tokensLocked, 1, tokens); - _createProvision(subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); + + // simulate locked tokens still thawing uint256 thawUntil = block.timestamp + 1; - _storeServiceProvider(users.indexer, tokens, 0, tokensLocked, thawUntil, 0); - vm.expectRevert(abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingStillThawing.selector, - thawUntil - )); + token.transfer(address(staking), tokens); + _setStorage_ServiceProvider(users.indexer, tokens, 0, tokensLocked, thawUntil, 0); + + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, tokens, 0, MAX_THAWING_PERIOD); + + vm.expectRevert(abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingStillThawing.selector, thawUntil)); staking.withdraw(); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/transfer-tools/ttools.t.sol b/packages/horizon/test/staking/transfer-tools/ttools.t.sol index c41731e10..11bb6e62d 100644 --- a/packages/horizon/test/staking/transfer-tools/ttools.t.sol +++ b/packages/horizon/test/staking/transfer-tools/ttools.t.sol @@ -1,16 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; -import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; -import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; contract HorizonStakingTransferToolsTest is HorizonStakingTest { - event Transfer(address indexed from, address indexed to, uint tokens); - /* * TESTS */ @@ -69,10 +65,10 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 resetPrank(users.indexer); - _createProvision(subgraphDataServiceLegacyAddress, 100 ether, 0, 0); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 100 ether, 0, 0); resetPrank(users.delegator); - _delegateLegacy(users.indexer, 1 ether); + _delegate(users.indexer, 1 ether); // send amount to staking contract - this should be done by the bridge resetPrank(users.delegator); @@ -92,10 +88,10 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 resetPrank(users.indexer); - _createProvision(subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); resetPrank(users.delegator); - _delegateLegacy(users.indexer, originalDelegationAmount); + _delegate(users.indexer, originalDelegationAmount); // send amount to staking contract - this should be done by the bridge resetPrank(users.delegator); @@ -103,7 +99,7 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { // thaw some delegation before receiving new delegation from L1 resetPrank(users.delegator); - _undelegateLegacy(users.indexer, originalDelegationAmount / 10); + _undelegate(users.indexer, originalDelegationAmount / 10); resetPrank(graphTokenGatewayAddress); bytes memory data = abi.encode( @@ -120,11 +116,11 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 resetPrank(users.indexer); - _createProvision(subgraphDataServiceLegacyAddress, provisionSize, 0, 1 days); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, provisionSize, 0, 1 days); // initialize the delegation pool resetPrank(users.delegator); - _delegateLegacy(users.indexer, originalDelegationAmount); + _delegate(users.indexer, originalDelegationAmount); // slash the entire provision resetPrank(subgraphDataServiceLegacyAddress); @@ -147,10 +143,10 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 resetPrank(users.indexer); - _createProvision(subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); + _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); resetPrank(users.delegator); - _delegateLegacy(users.indexer, amountDelegated); + _delegate(users.indexer, amountDelegated); // send amount to staking contract - this should be done by the bridge resetPrank(users.delegator); @@ -158,7 +154,7 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { // thaw all delegation before receiving new delegation from L1 resetPrank(users.delegator); - _undelegateLegacy(users.indexer, amountDelegated); + _undelegate(users.indexer, amountDelegated); resetPrank(graphTokenGatewayAddress); bytes memory data = abi.encode( @@ -166,89 +162,5 @@ contract HorizonStakingTransferToolsTest is HorizonStakingTest { abi.encode(users.indexer, users.delegator) ); _onTokenTransfer_ReceiveDelegation(counterpartStaking, amountReceived, data); - } - - /** - * HELPERS - */ - - function _onTokenTransfer_ReceiveDelegation(address from, uint256 tokens, bytes memory data) internal { - (, bytes memory fnData) = abi.decode(data, (uint8, bytes)); - (address serviceProvider, address delegator) = abi.decode(fnData, (address, address)); - bytes32 slotPoolTokens = bytes32(uint256(keccak256(abi.encode(serviceProvider, 20))) + 2); - - // before - DelegationPool memory beforePool = staking.getDelegationPool(serviceProvider, subgraphDataServiceLegacyAddress); - Delegation memory beforeDelegation = staking.getDelegation( - serviceProvider, - subgraphDataServiceLegacyAddress, - delegator - ); - uint256 beforeStoragePoolTokens = uint256(vm.load(address(staking), slotPoolTokens)); - uint256 beforeDelegatedTokens = staking.getDelegatedTokensAvailable( - serviceProvider, - subgraphDataServiceLegacyAddress - ); - uint256 beforeDelegatorBalance = token.balanceOf(delegator); - uint256 beforeStakingBalance = token.balanceOf(address(staking)); - uint256 calcShares = (beforePool.tokens == 0 || beforePool.tokens == beforePool.tokensThawing) - ? tokens - : ((tokens * beforePool.shares) / (beforePool.tokens - beforePool.tokensThawing)); - - bool earlyExit = (calcShares == 0 || tokens < 1 ether) || - (beforePool.tokens == 0 && (beforePool.shares != 0 || beforePool.sharesThawing != 0)); - - // onTokenTransfer - if (earlyExit) { - vm.expectEmit(); - emit Transfer(address(staking), delegator, tokens); - vm.expectEmit(); - emit IL2StakingBase.TransferredDelegationReturnedToDelegator(serviceProvider, delegator, tokens); - } else { - vm.expectEmit(); - emit IHorizonStakingExtension.StakeDelegated(serviceProvider, delegator, tokens, calcShares); - } - staking.onTokenTransfer(from, tokens, data); - - // after - DelegationPool memory afterPool = staking.getDelegationPool(serviceProvider, subgraphDataServiceLegacyAddress); - Delegation memory afterDelegation = staking.getDelegation( - serviceProvider, - subgraphDataServiceLegacyAddress, - delegator - ); - uint256 afterStoragePoolTokens = uint256(vm.load(address(staking), slotPoolTokens)); - uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable( - serviceProvider, - subgraphDataServiceLegacyAddress - ); - uint256 afterDelegatorBalance = token.balanceOf(delegator); - uint256 afterStakingBalance = token.balanceOf(address(staking)); - - uint256 deltaShares = afterDelegation.shares - beforeDelegation.shares; - - // assertions - if (earlyExit) { - assertEq(beforePool.tokens, afterPool.tokens); - assertEq(beforePool.shares, afterPool.shares); - assertEq(beforePool.tokensThawing, afterPool.tokensThawing); - assertEq(beforePool.sharesThawing, afterPool.sharesThawing); - assertEq(0, deltaShares); - assertEq(beforeDelegatedTokens, afterDelegatedTokens); - assertEq(beforeStoragePoolTokens, afterStoragePoolTokens); - assertEq(beforeDelegatorBalance + tokens, afterDelegatorBalance); - assertEq(beforeStakingBalance - tokens, afterStakingBalance); - } else { - assertEq(beforePool.tokens + tokens, afterPool.tokens); - assertEq(beforePool.shares + calcShares, afterPool.shares); - assertEq(beforePool.tokensThawing, afterPool.tokensThawing); - assertEq(beforePool.sharesThawing, afterPool.sharesThawing); - assertEq(calcShares, deltaShares); - assertEq(beforeDelegatedTokens + tokens, afterDelegatedTokens); - // Ensure correct slot is being updated, pools are stored in different storage locations for legacy subgraph data service - assertEq(beforeStoragePoolTokens + tokens, afterStoragePoolTokens); - assertEq(beforeDelegatorBalance, afterDelegatorBalance); - assertEq(beforeStakingBalance, afterStakingBalance); - } - } + } } diff --git a/packages/horizon/test/utilities/GraphDirectory.t.sol b/packages/horizon/test/utilities/GraphDirectory.t.sol index 35ab2a291..ece4afe65 100644 --- a/packages/horizon/test/utilities/GraphDirectory.t.sol +++ b/packages/horizon/test/utilities/GraphDirectory.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; diff --git a/packages/horizon/test/utilities/GraphDirectoryImplementation.sol b/packages/horizon/test/utilities/GraphDirectoryImplementation.sol index 57780f450..1095adc3a 100644 --- a/packages/horizon/test/utilities/GraphDirectoryImplementation.sol +++ b/packages/horizon/test/utilities/GraphDirectoryImplementation.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "../../contracts/interfaces/IHorizonStaking.sol"; diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index 29daaaa96..f08fa4ec1 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; abstract contract Constants { uint256 internal constant MAX_PPM = 1000000; // 100% in parts per million diff --git a/packages/horizon/test/utils/Users.sol b/packages/horizon/test/utils/Users.sol index 3329d69da..b26329f91 100644 --- a/packages/horizon/test/utils/Users.sol +++ b/packages/horizon/test/utils/Users.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; struct Users { address governor; diff --git a/packages/horizon/test/utils/Utils.sol b/packages/horizon/test/utils/Utils.sol index 47e4e68df..5aae4de3f 100644 --- a/packages/horizon/test/utils/Utils.sol +++ b/packages/horizon/test/utils/Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index a9afcff28..f48c20463 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHorizonStaking.sol"; diff --git a/packages/subgraph-service/contracts/DisputeManagerStorage.sol b/packages/subgraph-service/contracts/DisputeManagerStorage.sol index 8ff0685bf..a8790230d 100644 --- a/packages/subgraph-service/contracts/DisputeManagerStorage.sol +++ b/packages/subgraph-service/contracts/DisputeManagerStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDisputeManager } from "./interfaces/IDisputeManager.sol"; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 51cb889f7..5023e6160 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol index 54de429f1..e953dfba0 100644 --- a/packages/subgraph-service/contracts/SubgraphServiceStorage.sol +++ b/packages/subgraph-service/contracts/SubgraphServiceStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol index 73f7e56d6..95511ecc2 100644 --- a/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol +++ b/packages/subgraph-service/contracts/interfaces/IDisputeManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { Attestation } from "../libraries/Attestation.sol"; diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index e993c5159..e12554303 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataServiceFees.sol"; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index e039b75bd..a55034f17 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; diff --git a/packages/subgraph-service/contracts/libraries/Attestation.sol b/packages/subgraph-service/contracts/libraries/Attestation.sol index 0211db674..66a3cb5fb 100644 --- a/packages/subgraph-service/contracts/libraries/Attestation.sol +++ b/packages/subgraph-service/contracts/libraries/Attestation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title Attestation library diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol index 81e6bcdcb..83bef8037 100644 --- a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; /** * @title LegacyAllocation library diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 1a9c86928..2e40f28d3 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol index da812f5c1..f11e18d1b 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { Allocation } from "../libraries/Allocation.sol"; import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AttestationManager.sol b/packages/subgraph-service/contracts/utilities/AttestationManager.sol index 0d8405917..97c55ab8b 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { AttestationManagerV1Storage } from "./AttestationManagerStorage.sol"; diff --git a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol index 5bf57af65..5f86a19f3 100644 --- a/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AttestationManagerStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; abstract contract AttestationManagerV1Storage { /// @dev EIP712 domain separator diff --git a/packages/subgraph-service/contracts/utilities/Directory.sol b/packages/subgraph-service/contracts/utilities/Directory.sol index 920a0ae5e..53de7c6e7 100644 --- a/packages/subgraph-service/contracts/utilities/Directory.sol +++ b/packages/subgraph-service/contracts/utilities/Directory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; import { IDisputeManager } from "../interfaces/IDisputeManager.sol"; import { ISubgraphService } from "../interfaces/ISubgraphService.sol"; diff --git a/packages/subgraph-service/foundry.toml b/packages/subgraph-service/foundry.toml index 235a58eb9..9f5c3a92a 100644 --- a/packages/subgraph-service/foundry.toml +++ b/packages/subgraph-service/foundry.toml @@ -4,14 +4,6 @@ out = 'build' libs = ['node_modules', 'lib'] test = 'test' cache_path = 'cache_forge' +fs_permissions = [{ access = "read", path = "./"}] optimizer = true optimizer-runs = 200 -via_ir = true -fs_permissions = [{ access = "read", path = "./"}] - -[profile.lite] -optimizer = false -optimizer-runs = 1 - -[profile.lite.optimizer_details.yulDetails] -optimizerSteps = ':' \ No newline at end of file diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts index a8e05c779..17ebc2053 100644 --- a/packages/subgraph-service/hardhat.config.ts +++ b/packages/subgraph-service/hardhat.config.ts @@ -8,7 +8,7 @@ import { HardhatUserConfig } from 'hardhat/config' const config: HardhatUserConfig = { solidity: { - version: '0.8.26', + version: '0.8.27', settings: { viaIR: true, optimizer: { diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index da7b33a3d..bb5dd9ea9 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -10,7 +10,7 @@ "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", "build": "forge build && hardhat compile", - "test": "FOUNDRY_PROFILE=lite forge test -vvvv && hardhat test" + "test": "forge test && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 2fe5ccf64..d42b66e29 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol b/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol index 1077c1435..0d99aec0b 100644 --- a/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol +++ b/packages/subgraph-service/test/disputeManager/DisputeManager.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -166,54 +166,67 @@ contract DisputeManagerTest is SubgraphServiceSharedTest { return _disputeID; } + struct BeforeValues_CreateQueryDisputeConflict { + Attestation.State attestation1; + Attestation.State attestation2; + address indexer1; + address indexer2; + uint256 stakeSnapshot1; + uint256 stakeSnapshot2; + } function _createQueryDisputeConflict( bytes memory attestationData1, bytes memory attestationData2 ) internal returns (bytes32, bytes32) { (, address fisherman,) = vm.readCallers(); - Attestation.State memory attestation1 = Attestation.parse(attestationData1); - Attestation.State memory attestation2 = Attestation.parse(attestationData2); - address indexer1 = disputeManager.getAttestationIndexer(attestation1); - address indexer2 = disputeManager.getAttestationIndexer(attestation2); + + BeforeValues_CreateQueryDisputeConflict memory beforeValues; + beforeValues.attestation1 = Attestation.parse(attestationData1); + beforeValues.attestation2 = Attestation.parse(attestationData2); + beforeValues.indexer1 = disputeManager.getAttestationIndexer(beforeValues.attestation1); + beforeValues.indexer2 = disputeManager.getAttestationIndexer(beforeValues.attestation2); + beforeValues.stakeSnapshot1 = disputeManager.getStakeSnapshot(beforeValues.indexer1); + beforeValues.stakeSnapshot2 = disputeManager.getStakeSnapshot(beforeValues.indexer2); + bytes32 expectedDisputeId1 = keccak256( abi.encodePacked( - attestation1.requestCID, - attestation1.responseCID, - attestation1.subgraphDeploymentId, - indexer1, + beforeValues.attestation1.requestCID, + beforeValues.attestation1.responseCID, + beforeValues.attestation1.subgraphDeploymentId, + beforeValues.indexer1, fisherman ) ); bytes32 expectedDisputeId2 = keccak256( abi.encodePacked( - attestation2.requestCID, - attestation2.responseCID, - attestation2.subgraphDeploymentId, - indexer2, + beforeValues.attestation2.requestCID, + beforeValues.attestation2.responseCID, + beforeValues.attestation2.subgraphDeploymentId, + beforeValues.indexer2, fisherman ) ); - uint256 stakeSnapshot1 = disputeManager.getStakeSnapshot(indexer1); - uint256 stakeSnapshot2 = disputeManager.getStakeSnapshot(indexer2); + // createQueryDisputeConflict vm.expectEmit(address(disputeManager)); emit IDisputeManager.QueryDisputeCreated( expectedDisputeId1, - indexer1, + beforeValues.indexer1, fisherman, 0, - attestation1.subgraphDeploymentId, + beforeValues.attestation1.subgraphDeploymentId, attestationData1, - stakeSnapshot1 + beforeValues.stakeSnapshot1 ); + vm.expectEmit(address(disputeManager)); emit IDisputeManager.QueryDisputeCreated( expectedDisputeId2, - indexer2, + beforeValues.indexer2, fisherman, 0, - attestation2.subgraphDeploymentId, + beforeValues.attestation2.subgraphDeploymentId, attestationData2, - stakeSnapshot2 + beforeValues.stakeSnapshot2 ); (bytes32 _disputeId1, bytes32 _disputeId2) = disputeManager.createQueryDisputeConflict(attestationData1, attestationData2); @@ -226,24 +239,24 @@ contract DisputeManagerTest is SubgraphServiceSharedTest { // Check dispute values IDisputeManager.Dispute memory dispute1 = _getDispute(_disputeId1); - assertEq(dispute1.indexer, indexer1, "Indexer 1 should match"); + assertEq(dispute1.indexer, beforeValues.indexer1, "Indexer 1 should match"); assertEq(dispute1.fisherman, fisherman, "Fisherman 1 should match"); assertEq(dispute1.deposit, 0, "Deposit 1 should match"); assertEq(dispute1.relatedDisputeId, _disputeId2, "Related dispute ID 1 should be the id of the other dispute"); assertEq(uint8(dispute1.disputeType), uint8(IDisputeManager.DisputeType.QueryDispute), "Dispute type 1 should be query"); assertEq(uint8(dispute1.status), uint8(IDisputeManager.DisputeStatus.Pending), "Dispute status 1 should be pending"); assertEq(dispute1.createdAt, block.timestamp, "Created at 1 should match"); - assertEq(dispute1.stakeSnapshot, stakeSnapshot1, "Stake snapshot 1 should match"); + assertEq(dispute1.stakeSnapshot, beforeValues.stakeSnapshot1, "Stake snapshot 1 should match"); IDisputeManager.Dispute memory dispute2 = _getDispute(_disputeId2); - assertEq(dispute2.indexer, indexer2, "Indexer 2 should match"); + assertEq(dispute2.indexer, beforeValues.indexer2, "Indexer 2 should match"); assertEq(dispute2.fisherman, fisherman, "Fisherman 2 should match"); assertEq(dispute2.deposit, 0, "Deposit 2 should match"); assertEq(dispute2.relatedDisputeId, _disputeId1, "Related dispute ID 2 should be the id of the other dispute"); assertEq(uint8(dispute2.disputeType), uint8(IDisputeManager.DisputeType.QueryDispute), "Dispute type 2 should be query"); assertEq(uint8(dispute2.status), uint8(IDisputeManager.DisputeStatus.Pending), "Dispute status 2 should be pending"); assertEq(dispute2.createdAt, block.timestamp, "Created at 2 should match"); - assertEq(dispute2.stakeSnapshot, stakeSnapshot2, "Stake snapshot 2 should match"); + assertEq(dispute2.stakeSnapshot, beforeValues.stakeSnapshot2, "Stake snapshot 2 should match"); return (_disputeId1, _disputeId2); } diff --git a/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol b/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol index 76f90481a..c9166719f 100644 --- a/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol +++ b/packages/subgraph-service/test/disputeManager/constructor/constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol b/packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol index cd229dbc4..b6b4a6890 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/disputes.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol index 5e0d36132..49bee9e26 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/accept.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol index 0a09ad7f4..1639f2cad 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/cancel.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol index 0174315a2..8d1b75c21 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/create.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol index 3df590f74..7ce70d962 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/draw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol b/packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol index 5401c0afe..41b5adabc 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/indexing/reject.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol index d0f00234d..7670d381e 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/query/accept.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol index a61db6ad9..5a70e2f70 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/query/cancel.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol index 01f27cf66..4eba11744 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/query/create.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol index 1b9c96ad2..2ff182378 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/query/draw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol b/packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol index 07c738a90..fff210ea6 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/query/reject.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol index 1cfde0a8c..46a6d4bdd 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/accept.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol index 4de2b3155..36d14fab2 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/cancel.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol index 2f54983ae..edd2d545b 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/create.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol index 5127b56a5..5444936cc 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/draw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol index 078969267..ff347f7d2 100644 --- a/packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol +++ b/packages/subgraph-service/test/disputeManager/disputes/queryConflict/reject.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol b/packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol index 53e36a497..1277235fd 100644 --- a/packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol +++ b/packages/subgraph-service/test/disputeManager/governance/arbitrator.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol b/packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol index 163157886..1df13acb2 100644 --- a/packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol +++ b/packages/subgraph-service/test/disputeManager/governance/disputeDeposit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol b/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol index 5a09bdd03..3eddddc37 100644 --- a/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol +++ b/packages/subgraph-service/test/disputeManager/governance/fishermanRewardCut.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol b/packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol index 343e514bc..a554f774c 100644 --- a/packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol +++ b/packages/subgraph-service/test/disputeManager/governance/maxSlashingCut.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/mocks/MockCuration.sol b/packages/subgraph-service/test/mocks/MockCuration.sol index 68b4a8ce9..e0158a99e 100644 --- a/packages/subgraph-service/test/mocks/MockCuration.sol +++ b/packages/subgraph-service/test/mocks/MockCuration.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; +pragma solidity 0.8.27; contract MockCuration { function isCurated(bytes32) public pure returns (bool) { diff --git a/packages/subgraph-service/test/mocks/MockGRTToken.sol b/packages/subgraph-service/test/mocks/MockGRTToken.sol index d581f8299..7d21fd00a 100644 --- a/packages/subgraph-service/test/mocks/MockGRTToken.sol +++ b/packages/subgraph-service/test/mocks/MockGRTToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; diff --git a/packages/subgraph-service/test/mocks/MockRewardsManager.sol b/packages/subgraph-service/test/mocks/MockRewardsManager.sol index 59ca5577e..363fbf902 100644 --- a/packages/subgraph-service/test/mocks/MockRewardsManager.sol +++ b/packages/subgraph-service/test/mocks/MockRewardsManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/shared/HorizonStakingShared.t.sol b/packages/subgraph-service/test/shared/HorizonStakingShared.t.sol index 28a22e1a2..e07516903 100644 --- a/packages/subgraph-service/test/shared/HorizonStakingShared.t.sol +++ b/packages/subgraph-service/test/shared/HorizonStakingShared.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index 1067acf14..089fdd9a9 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 12d20581f..05c038680 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; @@ -30,7 +30,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { * MODIFIERS */ - modifier useOperator { + modifier useOperator() { resetPrank(users.indexer); staking.setOperator(users.operator, address(subgraphService), true); resetPrank(users.operator); @@ -38,7 +38,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { vm.stopPrank(); } - modifier useRewardsDestination { + modifier useRewardsDestination() { _setRewardsDestination(users.rewardsDestination); _; } @@ -74,10 +74,10 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { uint64 thawingPeriod = provision.thawingPeriod; uint32 maxVerifierCutPending = provision.maxVerifierCutPending; uint64 thawingPeriodPending = provision.thawingPeriodPending; - + vm.expectEmit(address(subgraphService)); emit IDataService.ProvisionAccepted(_indexer); - + // Accept provision subgraphService.acceptProvision(_indexer, _data); @@ -110,7 +110,13 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { } vm.expectEmit(address(subgraphService)); - emit AllocationManager.AllocationResized(_indexer, _allocationId, subgraphDeploymentId, _tokens, beforeSubgraphAllocatedTokens); + emit AllocationManager.AllocationResized( + _indexer, + _allocationId, + subgraphDeploymentId, + _tokens, + beforeSubgraphAllocatedTokens + ); // resize allocation subgraphService.resizeAllocation(_indexer, _allocationId, _tokens); @@ -119,8 +125,12 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { uint256 afterSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(subgraphDeploymentId); uint256 afterAllocatedTokens = subgraphService.allocationProvisionTracker(_indexer); Allocation.State memory afterAllocation = subgraphService.getAllocation(_allocationId); - uint256 accRewardsPerAllocatedTokenDelta = afterAllocation.accRewardsPerAllocatedToken - beforeAllocation.accRewardsPerAllocatedToken; - uint256 afterAccRewardsPending = rewardsManager.calcRewards(beforeAllocation.tokens, accRewardsPerAllocatedTokenDelta); + uint256 accRewardsPerAllocatedTokenDelta = afterAllocation.accRewardsPerAllocatedToken - + beforeAllocation.accRewardsPerAllocatedToken; + uint256 afterAccRewardsPending = rewardsManager.calcRewards( + beforeAllocation.tokens, + accRewardsPerAllocatedTokenDelta + ); // check state if (_tokens > beforeAllocation.tokens) { @@ -138,10 +148,17 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { assertTrue(subgraphService.isActiveAllocation(_allocationId)); Allocation.State memory allocation = subgraphService.getAllocation(_allocationId); - uint256 previousSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens(allocation.subgraphDeploymentId); - + uint256 previousSubgraphAllocatedTokens = subgraphService.getSubgraphAllocatedTokens( + allocation.subgraphDeploymentId + ); + vm.expectEmit(address(subgraphService)); - emit AllocationManager.AllocationClosed(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, allocation.tokens); + emit AllocationManager.AllocationClosed( + allocation.indexer, + _allocationId, + allocation.subgraphDeploymentId, + allocation.tokens + ); // close stale allocation subgraphService.closeStaleAllocation(_allocationId); @@ -182,15 +199,20 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { uint256 paymentCollected = 0; Allocation.State memory allocation; CollectPaymentData memory collectPaymentDataBefore; - + // PaymentType.IndexingRewards variables IndexingRewardsData memory indexingRewardsData; - uint32 delegationRatio = subgraphService.delegationRatio(); address rewardsDestination = subgraphService.rewardsDestination(_indexer); collectPaymentDataBefore.rewardsDestinationBalance = token.balanceOf(rewardsDestination); - collectPaymentDataBefore.indexerProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); - collectPaymentDataBefore.delegationPoolBalance = staking.getDelegatedTokensAvailable(_indexer, address(subgraphService)); - + collectPaymentDataBefore.indexerProvisionBalance = staking.getProviderTokensAvailable( + _indexer, + address(subgraphService) + ); + collectPaymentDataBefore.delegationPoolBalance = staking.getDelegatedTokensAvailable( + _indexer, + address(subgraphService) + ); + // PaymentType.QueryFee variables QueryFeeData memory queryFeeData; queryFeeData.protocolPaymentCut = graphPayments.PROTOCOL_PAYMENT_CUT(); @@ -257,25 +279,38 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { // Collect payment data after CollectPaymentData memory collectPaymentDataAfter; collectPaymentDataAfter.rewardsDestinationBalance = token.balanceOf(rewardsDestination); - collectPaymentDataAfter.indexerProvisionBalance = staking.getProviderTokensAvailable(_indexer, address(subgraphService)); - collectPaymentDataAfter.delegationPoolBalance = staking.getDelegatedTokensAvailable(_indexer, address(subgraphService)); + collectPaymentDataAfter.indexerProvisionBalance = staking.getProviderTokensAvailable( + _indexer, + address(subgraphService) + ); + collectPaymentDataAfter.delegationPoolBalance = staking.getDelegatedTokensAvailable( + _indexer, + address(subgraphService) + ); collectPaymentDataAfter.indexerBalance = token.balanceOf(_indexer); collectPaymentDataAfter.curationBalance = token.balanceOf(address(curation)); collectPaymentDataAfter.lockedTokens = subgraphService.feesProvisionTracker(_indexer); if (_paymentType == IGraphPayments.PaymentTypes.QueryFee) { // Check indexer got paid the correct amount - uint256 tokensProtocol = paymentCollected.mulPPM(protocolPaymentCut); - uint256 curationTokens = paymentCollected.mulPPM(queryFeeData.curationCut); - uint256 expectedIndexerTokensPayment = paymentCollected - tokensProtocol - curationTokens; - assertEq(collectPaymentDataAfter.indexerBalance, collectPaymentDataBefore.indexerBalance + expectedIndexerTokensPayment); + { + uint256 tokensProtocol = paymentCollected.mulPPM(protocolPaymentCut); + uint256 curationTokens = paymentCollected.mulPPM(queryFeeData.curationCut); + uint256 expectedIndexerTokensPayment = paymentCollected - tokensProtocol - curationTokens; + assertEq( + collectPaymentDataAfter.indexerBalance, + collectPaymentDataBefore.indexerBalance + expectedIndexerTokensPayment + ); - // Check curation got paid the correct amount - assertEq(collectPaymentDataAfter.curationBalance, collectPaymentDataBefore.curationBalance + curationTokens); + // Check curation got paid the correct amount + assertEq( + collectPaymentDataAfter.curationBalance, + collectPaymentDataBefore.curationBalance + curationTokens + ); + } // Check locked tokens - uint256 stakeToFeesRatio = subgraphService.stakeToFeesRatio(); - uint256 tokensToLock = paymentCollected * stakeToFeesRatio; + uint256 tokensToLock = paymentCollected * subgraphService.stakeToFeesRatio(); assertEq(collectPaymentDataAfter.lockedTokens, collectPaymentDataBefore.lockedTokens + tokensToLock); // Check the stake claim @@ -290,10 +325,12 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { } else { // Update allocation after collecting rewards allocation = subgraphService.getAllocation(allocationId); - + // Check allocation state assertEq(allocation.accRewardsPending, 0); - uint256 accRewardsPerAllocatedToken = rewardsManager.onSubgraphAllocationUpdate(allocation.subgraphDeploymentId); + uint256 accRewardsPerAllocatedToken = rewardsManager.onSubgraphAllocationUpdate( + allocation.subgraphDeploymentId + ); assertEq(allocation.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken); assertEq(allocation.lastPOIPresentedAt, block.timestamp); @@ -301,7 +338,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { if (rewardsDestination == address(0)) { // If rewards destination is address zero indexer should get paid to their provision balance assertEq( - collectPaymentDataAfter.indexerProvisionBalance, + collectPaymentDataAfter.indexerProvisionBalance, collectPaymentDataBefore.indexerProvisionBalance + indexingRewardsData.tokensIndexerRewards ); } else { @@ -314,12 +351,16 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { // Check delegation pool got paid the correct amount assertEq( - collectPaymentDataAfter.delegationPoolBalance, + collectPaymentDataAfter.delegationPoolBalance, collectPaymentDataBefore.delegationPoolBalance + indexingRewardsData.tokensDelegationRewards ); // If after collecting indexing rewards the indexer is over allocated the allcation should close - uint256 tokensAvailable = staking.getTokensAvailable(_indexer, address(subgraphService), delegationRatio); + uint256 tokensAvailable = staking.getTokensAvailable( + _indexer, + address(subgraphService), + subgraphService.delegationRatio() + ); if (allocation.tokens <= tokensAvailable) { // Indexer isn't over allocated so allocation should still be open assertTrue(allocation.isOpen()); diff --git a/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol b/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol index 3e6672dd7..68d736261 100644 --- a/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/allocation/resize.t.sol b/packages/subgraph-service/test/subgraphService/allocation/resize.t.sol index 3da7c5a0c..0df994929 100644 --- a/packages/subgraph-service/test/subgraphService/allocation/resize.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/resize.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/allocation/start.t.sol b/packages/subgraph-service/test/subgraphService/allocation/start.t.sol index 6db5e73db..9157444fb 100644 --- a/packages/subgraph-service/test/subgraphService/allocation/start.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/start.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol index 84b9da27e..ee5958115 100644 --- a/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol index 4891a4a75..9df747b4f 100644 --- a/packages/subgraph-service/test/subgraphService/collect/collect.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/collect.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol index d51f9ea4b..8b29ec830 100644 --- a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol index 9e20ad352..6ad7b5347 100644 --- a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/provider/register.t.sol b/packages/subgraph-service/test/subgraphService/provider/register.t.sol index 8e3d0577e..1df1f5571 100644 --- a/packages/subgraph-service/test/subgraphService/provider/register.t.sol +++ b/packages/subgraph-service/test/subgraphService/provider/register.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol b/packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol index 3926bc362..0b4c805b2 100644 --- a/packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol +++ b/packages/subgraph-service/test/subgraphService/provider/rewardsDestination.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol index 9fdb0b76f..1c8191275 100644 --- a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol +++ b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index e20d1fc72..1dbfd082e 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; abstract contract Constants { uint256 internal constant MAX_TOKENS = 10_000_000_000 ether; diff --git a/packages/subgraph-service/test/utils/Users.sol b/packages/subgraph-service/test/utils/Users.sol index b2976f98a..69c3e411e 100644 --- a/packages/subgraph-service/test/utils/Users.sol +++ b/packages/subgraph-service/test/utils/Users.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; struct Users { address governor; diff --git a/packages/subgraph-service/test/utils/Utils.sol b/packages/subgraph-service/test/utils/Utils.sol index 47e4e68df..5aae4de3f 100644 --- a/packages/subgraph-service/test/utils/Utils.sol +++ b/packages/subgraph-service/test/utils/Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.26; +pragma solidity 0.8.27; import "forge-std/Test.sol"; From 282ea51a471ab199fcf701e600e6d3178a7a0847 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 17 Sep 2024 18:03:40 +0100 Subject: [PATCH 201/277] fix: add security contact to DisputeManager.sol --- packages/subgraph-service/contracts/DisputeManager.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index f48c20463..7bc932782 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -19,7 +19,7 @@ import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/Graph import { DisputeManagerV1Storage } from "./DisputeManagerStorage.sol"; import { AttestationManager } from "./utilities/AttestationManager.sol"; -/* +/** * @title DisputeManager * @notice Provides a way to permissionlessly create disputes for incorrect behavior in the Subgraph Service. * @@ -40,6 +40,7 @@ import { AttestationManager } from "./utilities/AttestationManager.sol"; * Arbitration: * Disputes can only be accepted, rejected or drawn by the arbitrator role that can be delegated * to a EOA or DAO. + * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ */ contract DisputeManager is Initializable, From 491041bcd4d64eed502e158af27718343f03948c Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 17 Sep 2024 18:03:53 +0100 Subject: [PATCH 202/277] fix: add security contact to GraphPayments.sol --- packages/horizon/contracts/payments/GraphPayments.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index b7cb34db7..ea3063d81 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -16,6 +16,7 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; * @notice This contract is part of the Graph Horizon payments protocol. It's designed * to pull funds (GRT) from the {PaymentsEscrow} and distribute them according to a * set of pre established rules. + * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ */ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, IGraphPayments { using TokenUtils for IGraphToken; From 86fd039daf411b064792ccd06c74080ed3dd2b71 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 17 Sep 2024 18:30:19 +0100 Subject: [PATCH 203/277] fix: add security contact to HorizonStaking.sol --- packages/horizon/contracts/staking/HorizonStaking.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 74b2d8d09..ea64fccda 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -24,6 +24,7 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * This is due to the contract size limit on Arbitrum (24kB). The extension contract implements functionality to support * the legacy staking functions and the transfer tools. Both can be eventually removed without affecting the main * staking contract. + * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ */ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { using TokenUtils for IGraphToken; From 5ea1fe925147b3465d0373656bc1a0be64eeb783 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 17 Sep 2024 18:35:30 +0100 Subject: [PATCH 204/277] fix: add security contact to HorizonStakingExtension.sol --- packages/horizon/contracts/staking/HorizonStakingExtension.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index ba7eb3a5b..c6e6f5607 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -24,6 +24,7 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * without losing rewards or having service interruptions. * @dev TODO: Once the transition period and the transfer tools are deemed not necessary this contract * can be removed. It's expected the transition period to last for a full allocation cycle (28 epochs). + * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ */ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizonStakingExtension { using TokenUtils for IGraphToken; From c269117fbf90476c7427b1d40046da5a549bf1d5 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 17 Sep 2024 18:36:01 +0100 Subject: [PATCH 205/277] fix: add security contact to PaymentsEscrow.sol --- packages/horizon/contracts/payments/PaymentsEscrow.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 5d0694346..c7c4e72e5 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -17,6 +17,7 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; * @notice This contract is part of the Graph Horizon payments protocol. It holds the funds (GRT) * for payments made through the payments protocol for services provided * via a Graph Horizon data service. + * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ */ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, IPaymentsEscrow { using TokenUtils for IGraphToken; From 61a15440e9772d22a054b835e2dec5f1e8761b2f Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 17 Sep 2024 18:37:47 +0100 Subject: [PATCH 206/277] fix: add security contact to SubgraphService.sol + add NatSpec before contract def --- packages/subgraph-service/contracts/SubgraphService.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 5023e6160..0d2676476 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -21,6 +21,10 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; +/** + * @title SubgraphService contract + * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + */ contract SubgraphService is Initializable, OwnableUpgradeable, From d52be6d79e1967da01939cb8e8caba304f5f2ad5 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 17 Sep 2024 18:38:26 +0100 Subject: [PATCH 207/277] fix: add security contact to TAPCollector.sol --- packages/horizon/contracts/payments/collectors/TAPCollector.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index f3d67e819..fe96b78f3 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -17,6 +17,7 @@ import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; * @dev Note that the contract expects the RAV aggregate value to be monotonically increasing, each successive RAV for the same * (data service-payer-receiver) tuple should have a value greater than the previous one. The contract will keep track of the tokens * already collected and calculate the difference to collect. + * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ */ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { using PPMMath for uint256; From a58f807db20d1b7e82c0502a1995cd676d168fb2 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Wed, 18 Sep 2024 14:23:44 +0100 Subject: [PATCH 208/277] fix: change EIP712_ALLOCATION_PROOF_TYPEHASH from variable to constant. (OZ N-06) --- .../subgraph-service/contracts/utilities/AllocationManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 2e40f28d3..a6b719df4 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -30,7 +30,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca using TokenUtils for IGraphToken; ///@dev EIP712 typehash for allocation proof - bytes32 private immutable EIP712_ALLOCATION_PROOF_TYPEHASH = + bytes32 private constant EIP712_ALLOCATION_PROOF_TYPEHASH = keccak256("AllocationIdProof(address indexer,address allocationId)"); /** From 516a4e3bf2841d5ed764183e48e25df0a5dfc799 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Wed, 18 Sep 2024 17:24:44 +0100 Subject: [PATCH 209/277] fix: add override keyword in functions --- .../contracts/data-service/extensions/DataServicePausable.sol | 4 ++-- .../extensions/DataServicePausableUpgradeable.sol | 4 ++-- packages/subgraph-service/contracts/SubgraphService.sol | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol index 4d88cb72e..3c83fbb0e 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausable.sol @@ -30,14 +30,14 @@ abstract contract DataServicePausable is Pausable, DataService, IDataServicePaus /** * @notice See {IDataServicePausable-pause} */ - function pause() external onlyPauseGuardian whenNotPaused { + function pause() external override onlyPauseGuardian whenNotPaused { _pause(); } /** * @notice See {IDataServicePausable-pause} */ - function unpause() external onlyPauseGuardian whenPaused { + function unpause() external override onlyPauseGuardian whenPaused { _unpause(); } diff --git a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol index 52f27d9c4..82d7cc63b 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol @@ -26,14 +26,14 @@ abstract contract DataServicePausableUpgradeable is PausableUpgradeable, DataSer /** * @notice See {IDataServicePausable-pause} */ - function pause() external onlyPauseGuardian whenNotPaused { + function pause() external override onlyPauseGuardian whenNotPaused { _pause(); } /** * @notice See {IDataServicePausable-pause} */ - function unpause() external onlyPauseGuardian whenPaused { + function unpause() external override onlyPauseGuardian whenPaused { _unpause(); } diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 5023e6160..ce64d9ec0 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -351,7 +351,7 @@ contract SubgraphService is /** * @notice See {ISubgraphService.setRewardsDestination} */ - function setRewardsDestination(address rewardsDestination) external { + function setRewardsDestination(address rewardsDestination) external override { _setRewardsDestination(msg.sender, rewardsDestination); } From 9dfb8b0f1e7e3e454a8a249bcf86ce200bb38d84 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Wed, 18 Sep 2024 17:44:23 +0100 Subject: [PATCH 210/277] fix: remove unused return value. (OZ N-10) --- .../subgraph-service/contracts/utilities/AllocationManager.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 2e40f28d3..978335b58 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -396,7 +396,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * * @param _allocationId The id of the allocation to be closed */ - function _closeAllocation(address _allocationId) internal returns (Allocation.State memory) { + function _closeAllocation(address _allocationId) internal { Allocation.State memory allocation = allocations.get(_allocationId); // Take rewards snapshot to prevent other allos from counting tokens from this allo @@ -414,7 +414,6 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca allocation.tokens; emit AllocationClosed(allocation.indexer, _allocationId, allocation.subgraphDeploymentId, allocation.tokens); - return allocations[_allocationId]; } /** From bd62e959dadf8b011b7d3cf766d2cf1103b50120 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Wed, 18 Sep 2024 17:58:49 +0100 Subject: [PATCH 211/277] fix: remove unused return values from the Allocation library. (OZ N-10) --- .../contracts/libraries/Allocation.sol | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/packages/subgraph-service/contracts/libraries/Allocation.sol b/packages/subgraph-service/contracts/libraries/Allocation.sol index a55034f17..320547f92 100644 --- a/packages/subgraph-service/contracts/libraries/Allocation.sol +++ b/packages/subgraph-service/contracts/libraries/Allocation.sol @@ -96,12 +96,10 @@ library Allocation { * @param self The allocation list mapping * @param allocationId The allocation id */ - function presentPOI(mapping(address => State) storage self, address allocationId) internal returns (State memory) { + function presentPOI(mapping(address => State) storage self, address allocationId) internal { State storage allocation = _get(self, allocationId); require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.lastPOIPresentedAt = block.timestamp; - - return allocation; } /** @@ -116,12 +114,10 @@ library Allocation { mapping(address => State) storage self, address allocationId, uint256 accRewardsPerAllocatedToken - ) internal returns (State memory) { + ) internal { State storage allocation = _get(self, allocationId); require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; - - return allocation; } /** @@ -131,15 +127,10 @@ library Allocation { * @param self The allocation list mapping * @param allocationId The allocation id */ - function clearPendingRewards( - mapping(address => State) storage self, - address allocationId - ) internal returns (State memory) { + function clearPendingRewards(mapping(address => State) storage self, address allocationId) internal { State storage allocation = _get(self, allocationId); require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.accRewardsPending = 0; - - return allocation; } /** @@ -149,12 +140,10 @@ library Allocation { * @param self The allocation list mapping * @param allocationId The allocation id */ - function close(mapping(address => State) storage self, address allocationId) internal returns (State memory) { + function close(mapping(address => State) storage self, address allocationId) internal { State storage allocation = _get(self, allocationId); require(allocation.isOpen(), AllocationClosed(allocationId, allocation.closedAt)); allocation.closedAt = block.timestamp; - - return allocation; } /** From ffe9b89775af33d5aedff2c5757d14b819c80e94 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Wed, 18 Sep 2024 19:14:11 +0100 Subject: [PATCH 212/277] fix: address magic number use. (OZ N-11) --- .../data-service/utilities/ProvisionManager.sol | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index d1cf94287..ee5f5e048 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -23,6 +23,14 @@ import { ProvisionManagerV1Storage } from "./ProvisionManagerStorage.sol"; abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionManagerV1Storage { using UintRange for uint256; + // Constants + uint32 private constant DEFAULT_MIN_UINT32 = 0; + uint64 private constant DEFAULT_MIN_UINT64 = 0; + uint256 private constant DEFAULT_MIN_UINT256 = 0; + uint64 private constant DEFAULT_MAX_UINT64 = type(uint64).max; + uint256 private constant DEFAULT_MAX_UINT256 = type(uint256).max; + uint32 private constant MAX_PPM = uint32(PPMMath.MAX_PPM); + /** * @notice Emitted when the provision tokens range is set. * @param min The minimum allowed value for the provision tokens. @@ -115,9 +123,9 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa */ // solhint-disable-next-line func-name-mixedcase function __ProvisionManager_init_unchained() internal onlyInitializing { - _setProvisionTokensRange(type(uint256).min, type(uint256).max); - _setVerifierCutRange(type(uint32).min, uint32(PPMMath.MAX_PPM)); - _setThawingPeriodRange(type(uint64).min, type(uint64).max); + _setProvisionTokensRange(DEFAULT_MIN_UINT256, DEFAULT_MAX_UINT256); + _setVerifierCutRange(DEFAULT_MIN_UINT32, MAX_PPM); + _setThawingPeriodRange(DEFAULT_MIN_UINT64, DEFAULT_MAX_UINT64); } /** From 374f57d015dd6f6f0b44507e217b46193c3d1e7b Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Thu, 19 Sep 2024 15:08:08 +0100 Subject: [PATCH 213/277] fix: typographical errors throughout codebase. (OZ N-07) --- packages/contracts/contracts/curation/Curation.sol | 4 ++-- packages/contracts/contracts/curation/ICuration.sol | 4 ++-- .../contracts/contracts/l2/curation/L2Curation.sol | 6 +++--- .../contracts/contracts/rewards/IRewardsIssuer.sol | 4 ++-- packages/contracts/contracts/staking/Staking.sol | 2 +- packages/contracts/contracts/staking/libs/Stakes.sol | 2 +- .../horizon/contracts/interfaces/ITAPCollector.sol | 2 +- .../interfaces/internal/IHorizonStakingExtension.sol | 2 +- .../interfaces/internal/IHorizonStakingMain.sol | 12 ++++++------ .../interfaces/internal/IHorizonStakingTypes.sol | 4 ++-- .../horizon/contracts/payments/GraphPayments.sol | 2 +- .../horizon/contracts/staking/HorizonStaking.sol | 4 ++-- .../horizon/contracts/staking/HorizonStakingBase.sol | 2 +- .../contracts/staking/HorizonStakingExtension.sol | 6 +++--- .../subgraph-service/contracts/DisputeManager.sol | 2 +- .../contracts/utilities/AllocationManager.sol | 4 ++-- 16 files changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/contracts/contracts/curation/Curation.sol b/packages/contracts/contracts/curation/Curation.sol index bd3032046..e289d048c 100644 --- a/packages/contracts/contracts/curation/Curation.sol +++ b/packages/contracts/contracts/curation/Curation.sol @@ -257,7 +257,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) { @@ -286,7 +286,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) { diff --git a/packages/contracts/contracts/curation/ICuration.sol b/packages/contracts/contracts/curation/ICuration.sol index fe2f0e929..4f2c2bac5 100644 --- a/packages/contracts/contracts/curation/ICuration.sol +++ b/packages/contracts/contracts/curation/ICuration.sol @@ -84,14 +84,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/l2/curation/L2Curation.sol b/packages/contracts/contracts/l2/curation/L2Curation.sol index 3f8728d0a..f6d64209b 100644 --- a/packages/contracts/contracts/l2/curation/L2Curation.sol +++ b/packages/contracts/contracts/l2/curation/L2Curation.sol @@ -147,7 +147,7 @@ contract L2Curation is CurationV3Storage, GraphUpgradeable, IL2Curation { /** * @notice Assign Graph Tokens collected as curation fees to the curation pool reserve. - * @dev This function can only be called by the Staking contract and will do the bookeeping of + * @dev This function can only be called by the Staking contract and will do the Bookkeeping of * transferred tokens into this contract. * @param _subgraphDeploymentID SubgraphDeployment where funds should be allocated as reserves * @param _tokens Amount of Graph Tokens to add to reserves @@ -326,7 +326,7 @@ contract L2Curation is CurationV3Storage, 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) { @@ -355,7 +355,7 @@ contract L2Curation is CurationV3Storage, 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) { diff --git a/packages/contracts/contracts/rewards/IRewardsIssuer.sol b/packages/contracts/contracts/rewards/IRewardsIssuer.sol index 705ce8db8..fe6963fa7 100644 --- a/packages/contracts/contracts/rewards/IRewardsIssuer.sol +++ b/packages/contracts/contracts/rewards/IRewardsIssuer.sol @@ -33,9 +33,9 @@ interface IRewardsIssuer { function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentId) external view returns (uint256); /** - * @notice Wether or not an allocation is active (i.e open) + * @notice Whether or not an allocation is active (i.e open) * @param _allocationId Allocation Id - * @return Wether or not the allocation is active + * @return Whether or not the allocation is active */ function isActiveAllocation(address _allocationId) external view returns (bool); } diff --git a/packages/contracts/contracts/staking/Staking.sol b/packages/contracts/contracts/staking/Staking.sol index d44d4767e..6aef50efc 100644 --- a/packages/contracts/contracts/staking/Staking.sol +++ b/packages/contracts/contracts/staking/Staking.sol @@ -912,7 +912,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M if (curationFees > 0) { // Transfer and call collect() // This function transfer tokens to a trusted protocol contracts - // Then we call collect() to do the transfer bookeeping + // Then we call collect() to do the transfer Bookkeeping rewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); TokenUtils.pushTokens(_graphToken, address(curation), curationFees); curation.collect(_subgraphDeploymentID, curationFees); diff --git a/packages/contracts/contracts/staking/libs/Stakes.sol b/packages/contracts/contracts/staking/libs/Stakes.sol index b0524b14c..e856cdec1 100644 --- a/packages/contracts/contracts/staking/libs/Stakes.sol +++ b/packages/contracts/contracts/staking/libs/Stakes.sol @@ -85,7 +85,7 @@ library Stakes { /** * @dev 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); diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index e7b5bc4fd..6cfc16485 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -35,7 +35,7 @@ interface ITAPCollector is IPaymentsCollector { } /** - * Trown when the caller is not the data service the RAV was issued to + * Thrown when the caller is not the data service the RAV was issued to * @param caller The address of the caller * @param dataService The address of the data service */ diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index 6e29cb5c9..fcf70cc32 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -162,7 +162,7 @@ interface IHorizonStakingExtension is IRewardsIssuer, IL2StakingBase { function isAllocation(address allocationID) external view returns (bool); /** - * @notice Retrun the time in blocks to unstake + * @notice Return the time in blocks to unstake * @return Thawing period in blocks */ // solhint-disable-next-line func-name-mixedcase diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 418459d9f..ed7e90804 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -253,7 +253,7 @@ interface IHorizonStakingMain { * @param thawRequestId The ID of the thaw request * @param tokens The amount of tokens being released * @param shares The amount of shares being released - * @param thawingUntil The timestamp until the stake has thawn + * @param thawingUntil The timestamp until the stake has thawed */ event ThawRequestFulfilled(bytes32 indexed thawRequestId, uint256 tokens, uint256 shares, uint64 thawingUntil); @@ -417,7 +417,7 @@ interface IHorizonStakingMain { error HorizonStakingStillThawing(uint256 until); /** - * @notice Thrown when a service provider attempts to operate on verifieres that are not allowed. + * @notice Thrown when a service provider attempts to operate on verifiers that are not allowed. * @dev Only applies to stake from locked wallets. */ error HorizonStakingVerifierNotAllowed(address verifier); @@ -578,7 +578,7 @@ interface IHorizonStakingMain { /** * @notice Remove tokens from a provision and move them back to the service provider's idle stake. * @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw - * requests in the event that fulfulling all of them results in a gas limit error. + * requests in the event that fulfilling all of them results in a gas limit error. * * Requirements: * - Must have previously initiated a thaw request using {thaw}. @@ -704,7 +704,7 @@ interface IHorizonStakingMain { * @notice Withdraw undelegated tokens from a provision after thawing. * Tokens can be automatically re-delegated to another provision by setting `newServiceProvider`. * @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw - * requests in the event that fulfulling all of them results in a gas limit error. + * requests in the event that fulfilling all of them results in a gas limit error. * * Requirements: * - Must have previously initiated a thaw request using {undelegate}. @@ -744,7 +744,7 @@ interface IHorizonStakingMain { /** * @notice Delegate tokens to the subgraph data service provision. * This function is for backwards compatibility with the legacy staking contract. - * It only allows delegting to the subgraph data service and DOES NOT have slippage protection. + * It only allows delegating to the subgraph data service and DOES NOT have slippage protection. * @dev See {delegate}. * @param serviceProvider The service provider address * @param tokens The amount of tokens to delegate @@ -754,7 +754,7 @@ interface IHorizonStakingMain { /** * @notice Undelegate tokens from the subgraph data service provision and start thawing them. * This function is for backwards compatibility with the legacy staking contract. - * It only allows undelegting from the subgraph data service. + * It only allows undelegating from the subgraph data service. * @dev See {undelegate}. * @param serviceProvider The service provider address * @param shares The amount of shares to undelegate diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index eef8098e6..42b5588ef 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -39,7 +39,7 @@ interface IHorizonStakingTypes { * @dev See {ServiceProviderInternal} for the actual storage representation */ struct ServiceProvider { - // Total amount of tokens on the provider stake (only staked by the provider, inludes all provisions) + // Total amount of tokens on the provider stake (only staked by the provider, includes all provisions) uint256 tokensStaked; // Total amount of tokens locked in provisions (only staked by the provider) uint256 tokensProvisioned; @@ -50,7 +50,7 @@ interface IHorizonStakingTypes { * @dev It contains deprecated fields from the `Indexer` struct to maintain storage compatibility. */ struct ServiceProviderInternal { - // Total amount of tokens on the provider stake (only staked by the provider, inludes all provisions) + // Total amount of tokens on the provider stake (only staked by the provider, includes all provisions) uint256 tokensStaked; // (Deprecated) Tokens used in allocations uint256 __DEPRECATED_tokensAllocated; // solhint-disable-line graph/leading-underscore diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index b7cb34db7..05fbcb066 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -24,7 +24,7 @@ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, I /** * @notice Constructor for the {GraphPayments} contract - * @dev This contract is upgradeable however we stil use the constructor to set + * @dev This contract is upgradeable however we still use the constructor to set * a few immutable variables. * @param controller The address of the Graph controller * @param protocolPaymentCut The protocol tax in PPM diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 74b2d8d09..e36d33a73 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -62,7 +62,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } /** - * @dev The staking contract is upgradeable however we stil use the constructor to set + * @dev The staking contract is upgradeable however we still use the constructor to set * a few immutable variables. * @param controller The address of the Graph controller contract. * @param stakingExtensionAddress The address of the staking extension contract. @@ -903,7 +903,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * * @param _thawRequestId The ID of the current thaw request * @param _acc The accumulator data for the thaw requests being fulfilled - * @return Wether the thaw request is still thawing, indicating that the traversal should continue or stop. + * @return Whether the thaw request is still thawing, indicating that the traversal should continue or stop. * @return The updated accumulator data */ function _fulfillThawRequest(bytes32 _thawRequestId, bytes memory _acc) private returns (bool, bytes memory) { diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index b3e94c7ea..b55b39fd8 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -39,7 +39,7 @@ abstract contract HorizonStakingBase is address internal immutable SUBGRAPH_DATA_SERVICE_ADDRESS; /** - * @dev The staking contract is upgradeable however we stil use the constructor to set + * @dev The staking contract is upgradeable however we still use the constructor to set * a few immutable variables. * @param controller The address of the Graph controller contract. * @param subgraphDataServiceAddress The address of the subgraph data service. diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index ba7eb3a5b..66efe5521 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -41,7 +41,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon } /** - * @dev The staking contract is upgradeable however we stil use the constructor to set + * @dev The staking contract is upgradeable however we still use the constructor to set * a few immutable variables. * @param controller The address of the Graph controller contract. * @param subgraphDataServiceAddress The address of the subgraph data service. @@ -296,7 +296,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon } /** - * @notice Retrun the time in blocks to unstake + * @notice Return the time in blocks to unstake * Deprecated, now enforced by each data service (verifier) * @return Thawing period in blocks */ @@ -569,7 +569,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon if (curationFees > 0) { // Transfer and call collect() // This function transfer tokens to a trusted protocol contracts - // Then we call collect() to do the transfer bookeeping + // Then we call collect() to do the transfer Bookkeeping _graphRewardsManager().onSubgraphSignalUpdate(_subgraphDeploymentID); _graphToken().pushTokens(address(curation), curationFees); curation.collect(_subgraphDeploymentID, curationFees); diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index f48c20463..8bf0f363b 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -272,7 +272,7 @@ contract DisputeManager is } /** - * @notice Once the dispute period ends, if the disput status remains Pending, + * @notice Once the dispute period ends, if the dispute status remains Pending, * the fisherman can cancel the dispute and get back their initial deposit. * @dev Cancel a dispute with Id `disputeId` * @param disputeId Id of the dispute to be cancelled diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 2e40f28d3..e0d3ea036 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -142,7 +142,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca error AllocationManagerZeroTokensAllocation(address allocationId); /** - * @notice Thrown when attempting to collect indexing rewards on a closed allocationl + * @notice Thrown when attempting to collect indexing rewards on a closed allocation * @param allocationId The id of the allocation */ error AllocationManagerAllocationClosed(address allocationId); @@ -454,7 +454,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca } /** - * @notice Verifies ownsership of an allocation id by verifying an EIP712 allocation proof + * @notice Verifies ownership of an allocation id by verifying an EIP712 allocation proof * @dev Requirements: * - Signer must be the allocation id address * @param _indexer The address of the indexer From 79f7828bb96c76524c3e07e8fd87a713695ea916 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Thu, 19 Sep 2024 18:28:37 +0100 Subject: [PATCH 214/277] fix: reorder parameter use in mulPPM function call in mulPPMRoundUp. (OZ N-12) --- packages/horizon/contracts/libraries/PPMMath.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/libraries/PPMMath.sol b/packages/horizon/contracts/libraries/PPMMath.sol index 5bd636add..38b653954 100644 --- a/packages/horizon/contracts/libraries/PPMMath.sol +++ b/packages/horizon/contracts/libraries/PPMMath.sol @@ -42,7 +42,7 @@ library PPMMath { */ function mulPPMRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { require(isValidPPM(b), PPMMathInvalidPPM(b)); - return a - mulPPM(MAX_PPM - b, a); + return a - mulPPM(a, MAX_PPM - b); } /** From 4354737396d8503b35b3e0bdfceddd1cd3230c1d Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Fri, 20 Sep 2024 05:08:03 +1000 Subject: [PATCH 215/277] fix: only add to delegation pool if shares is greater than 0 (#1031) --- .../contracts/utilities/AllocationManager.sol | 8 ++++- .../subgraphService/SubgraphService.t.sol | 6 ++-- .../collect/indexing/indexing.t.sol | 31 +++++++++++++++++-- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index c277e2e9e..9604f92bb 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.27; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; +import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol"; import { GraphDirectory } from "@graphprotocol/horizon/contracts/utilities/GraphDirectory.sol"; import { AllocationManagerV1Storage } from "./AllocationManagerStorage.sol"; @@ -289,7 +290,12 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca address(this), IGraphPayments.PaymentTypes.IndexingFee ); - tokensDelegationRewards = tokensRewards.mulPPM(delegatorCut); + IHorizonStakingTypes.DelegationPool memory delegationPool = _graphStaking().getDelegationPool( + allocation.indexer, + address(this) + ); + // If delegation pool has no shares then we don't need to distribute rewards to delegators + tokensDelegationRewards = delegationPool.shares > 0 ? tokensRewards.mulPPM(delegatorCut) : 0; if (tokensDelegationRewards > 0) { _graphToken().approve(address(_graphStaking()), tokensDelegationRewards); _graphStaking().addToDelegationPool(allocation.indexer, address(this), tokensDelegationRewards); diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 05c038680..845a7b7fb 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -11,6 +11,7 @@ import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPC import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { LinkedList } from "@graphprotocol/horizon/contracts/libraries/LinkedList.sol"; import { IDataServiceFees } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataServiceFees.sol"; +import { IHorizonStakingTypes } from "@graphprotocol/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol"; import { Allocation } from "../../contracts/libraries/Allocation.sol"; import { AllocationManager } from "../../contracts/utilities/AllocationManager.sol"; @@ -255,7 +256,8 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead IGraphPayments.PaymentTypes.IndexingFee ); - indexingRewardsData.tokensDelegationRewards = paymentCollected.mulPPM(delegatorCut); + IHorizonStakingTypes.DelegationPool memory delegationPool = staking.getDelegationPool(allocation.indexer, address(subgraphService)); + indexingRewardsData.tokensDelegationRewards = delegationPool.shares > 0 ? paymentCollected.mulPPM(delegatorCut) : 0; indexingRewardsData.tokensIndexerRewards = paymentCollected - indexingRewardsData.tokensDelegationRewards; vm.expectEmit(address(subgraphService)); @@ -322,7 +324,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { assertEq(stakeClaim.createdAt, block.timestamp); assertEq(stakeClaim.releaseAt, block.timestamp + disputePeriod); assertEq(stakeClaim.nextClaim, bytes32(0)); - } else { + } else if (_paymentType == IGraphPayments.PaymentTypes.IndexingRewards) { // Update allocation after collecting rewards allocation = subgraphService.getAllocation(allocationId); diff --git a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol index 8b29ec830..ae2a085ed 100644 --- a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol @@ -27,14 +27,38 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { uint256 delegationTokens, uint256 delegationFeeCut ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { + // Collect reverts if delegationFeeCut is 100% + delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM - 1); + _setDelegationFeeCut( + users.indexer, + address(subgraphService), + // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead + IGraphPayments.PaymentTypes.IndexingFee, + delegationFeeCut + ); + IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; + bytes memory data = abi.encode(allocationID, bytes32("POI")); + _collect(users.indexer, paymentType, data); + } + + function test_SubgraphService_Collect_Indexing_AfterUndelegate( + uint256 tokens, + uint256 delegationTokens, + uint256 delegationFeeCut + ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { + // Collect reverts if delegationFeeCut is 100% delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM); _setDelegationFeeCut( users.indexer, address(subgraphService), // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead IGraphPayments.PaymentTypes.IndexingFee, - 100_000 + delegationFeeCut ); + // Undelegate + resetPrank(users.delegator); + staking.undelegate(users.indexer, address(subgraphService), delegationTokens); + resetPrank(users.indexer); IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; bytes memory data = abi.encode(allocationID, bytes32("POI")); _collect(users.indexer, paymentType, data); @@ -68,13 +92,14 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { uint256 delegationTokens, uint256 delegationFeeCut ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { - delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM); + // Collect reverts if delegationFeeCut is 100% + delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM - 1); _setDelegationFeeCut( users.indexer, address(subgraphService), // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead IGraphPayments.PaymentTypes.IndexingFee, - 100_000 + delegationFeeCut ); uint8 numberOfPOIs = 20; From fe380e46d9262f87b8b98c5caa88c53e2113abe4 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Fri, 20 Sep 2024 05:09:13 +1000 Subject: [PATCH 216/277] fix(SubgraphService): use correct payment type for collect indexing rewards (#1032) --- .../contracts/utilities/AllocationManager.sol | 2 +- .../test/subgraphService/SubgraphService.t.sol | 3 +-- .../test/subgraphService/collect/indexing/indexing.t.sol | 9 +++------ 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 9604f92bb..04a6e09dc 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -288,7 +288,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca uint256 delegatorCut = _graphStaking().getDelegationFeeCut( allocation.indexer, address(this), - IGraphPayments.PaymentTypes.IndexingFee + IGraphPayments.PaymentTypes.IndexingRewards ); IHorizonStakingTypes.DelegationPool memory delegationPool = _graphStaking().getDelegationPool( allocation.indexer, diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 845a7b7fb..b5b7f744e 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -253,8 +253,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { uint256 delegatorCut = staking.getDelegationFeeCut( allocation.indexer, address(subgraphService), - // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead - IGraphPayments.PaymentTypes.IndexingFee + IGraphPayments.PaymentTypes.IndexingRewards ); IHorizonStakingTypes.DelegationPool memory delegationPool = staking.getDelegationPool(allocation.indexer, address(subgraphService)); indexingRewardsData.tokensDelegationRewards = delegationPool.shares > 0 ? paymentCollected.mulPPM(delegatorCut) : 0; diff --git a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol index ae2a085ed..bff35f574 100644 --- a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol @@ -32,8 +32,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { _setDelegationFeeCut( users.indexer, address(subgraphService), - // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead - IGraphPayments.PaymentTypes.IndexingFee, + IGraphPayments.PaymentTypes.IndexingRewards, delegationFeeCut ); IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards; @@ -51,8 +50,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { _setDelegationFeeCut( users.indexer, address(subgraphService), - // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead - IGraphPayments.PaymentTypes.IndexingFee, + IGraphPayments.PaymentTypes.IndexingRewards, delegationFeeCut ); // Undelegate @@ -97,8 +95,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { _setDelegationFeeCut( users.indexer, address(subgraphService), - // TODO: this should be fixed in AllocationManager, it should be IndexingRewards instead - IGraphPayments.PaymentTypes.IndexingFee, + IGraphPayments.PaymentTypes.IndexingRewards, delegationFeeCut ); From 95b3f83b1abe85449a63ab4922e84896f989ac57 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Fri, 20 Sep 2024 05:10:11 +1000 Subject: [PATCH 217/277] fix(Horizon): only allow addToDelegationPool if provision exists and pool has shares (#1042) --- .../internal/IHorizonStakingMain.sol | 7 + .../contracts/staking/HorizonStaking.sol | 8 + packages/horizon/test/escrow/collect.t.sol | 147 +++++++++++++++-- .../horizon/test/payments/GraphPayments.t.sol | 149 ++++++++++++++++-- .../test/staking/delegation/addToPool.t.sol | 63 +++++--- 5 files changed, 324 insertions(+), 50 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index ed7e90804..eafce457a 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -402,6 +402,13 @@ interface IHorizonStakingMain { */ error HorizonStakingInvalidDelegationPoolState(address serviceProvider, address verifier); + /** + * @notice Thrown when attempting to operate with a delegation pool that does not exist. + * @param serviceProvider The service provider address + * @param verifier The verifier address + */ + error HorizonStakingInvalidDelegationPool(address serviceProvider, address verifier); + // -- Errors: thaw requests -- error HorizonStakingNothingThawing(); diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index e36d33a73..c8709e639 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -279,7 +279,15 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 tokens ) external override notPaused { require(tokens != 0, HorizonStakingInvalidZeroTokens()); + + // Provision must exist before adding to delegation pool + Provision memory prov = _provisions[serviceProvider][verifier]; + require(prov.createdAt != 0, HorizonStakingInvalidProvision(serviceProvider, verifier)); + + // Delegation pool must exist before adding tokens DelegationPoolInternal storage pool = _getDelegationPool(serviceProvider, verifier); + require(pool.shares > 0, HorizonStakingInvalidDelegationPool(serviceProvider, verifier)); + pool.tokens = pool.tokens + tokens; _graphToken().pullTokens(msg.sender, tokens); emit TokensToDelegationPoolAdded(serviceProvider, verifier, tokens); diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index 67efcc6e7..cbf945515 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.27; import "forge-std/Test.sol"; +import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; import { IPaymentsEscrow } from "../../contracts/interfaces/IPaymentsEscrow.sol"; @@ -10,30 +11,107 @@ import { GraphEscrowTest } from "./GraphEscrow.t.sol"; contract GraphEscrowCollectTest is GraphEscrowTest { + struct CollectPaymentData { + uint256 escrowBalance; + uint256 paymentsBalance; + uint256 receiverBalance; + uint256 delegationPoolBalance; + uint256 dataServiceBalance; + } + + function _collect( + IGraphPayments.PaymentTypes _paymentType, + address _payer, + address _receiver, + uint256 _tokens, + address _dataService, + uint256 _tokensDataService + ) private { + // Previous balances + (uint256 previousPayerEscrowBalance,,) = escrow.escrowAccounts(_payer, _receiver); + CollectPaymentData memory previousBalances = CollectPaymentData({ + escrowBalance: token.balanceOf(address(escrow)), + paymentsBalance: token.balanceOf(address(payments)), + receiverBalance: token.balanceOf(_receiver), + delegationPoolBalance: staking.getDelegatedTokensAvailable( + _receiver, + _dataService + ), + dataServiceBalance: token.balanceOf(_dataService) + }); + + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.EscrowCollected(_payer, _receiver, _tokens); + escrow.collect(_paymentType, _payer, _receiver, _tokens, _dataService, _tokensDataService); + + // Calculate cuts + uint256 protocolPaymentCut = payments.PROTOCOL_PAYMENT_CUT(); + uint256 delegatorCut = staking.getDelegationFeeCut( + _receiver, + _dataService, + _paymentType + ); + uint256 tokensProtocol = _tokens * protocolPaymentCut / MAX_PPM; + uint256 tokensDelegation = _tokens * delegatorCut / MAX_PPM; + + // After balances + (uint256 afterPayerEscrowBalance,,) = escrow.escrowAccounts(_payer, _receiver); + CollectPaymentData memory afterBalances = CollectPaymentData({ + escrowBalance: token.balanceOf(address(escrow)), + paymentsBalance: token.balanceOf(address(payments)), + receiverBalance: token.balanceOf(_receiver), + delegationPoolBalance: staking.getDelegatedTokensAvailable( + _receiver, + _dataService + ), + dataServiceBalance: token.balanceOf(_dataService) + }); + + // Check receiver balance after payment + uint256 receiverExpectedPayment = _tokens - _tokensDataService - tokensProtocol - tokensDelegation; + assertEq(afterBalances.receiverBalance - previousBalances.receiverBalance, receiverExpectedPayment); + assertEq(token.balanceOf(address(payments)), 0); + + // Check delegation pool balance after payment + assertEq(afterBalances.delegationPoolBalance - previousBalances.delegationPoolBalance, tokensDelegation); + + // Check that the escrow account has been updated + assertEq(previousBalances.escrowBalance, afterBalances.escrowBalance + _tokens); + + // Check that payments balance didn't change + assertEq(previousBalances.paymentsBalance, afterBalances.paymentsBalance); + + // Check data service balance after payment + assertEq(afterBalances.dataServiceBalance - previousBalances.dataServiceBalance, _tokensDataService); + + // Check payers escrow balance after payment + assertEq(previousPayerEscrowBalance - _tokens, afterPayerEscrowBalance); + } + /* * TESTS */ function testCollect_Tokens( - uint256 amount, + uint256 tokens, + uint256 delegationTokens, uint256 tokensDataService - ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { - uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; - uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; - vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); - - vm.startPrank(users.gateway); - escrow.approveCollector(users.verifier, amount); - _depositTokens(amount); + ) public useIndexer useProvision(tokens, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { + uint256 tokensProtocol = tokens * protocolPaymentCut / MAX_PPM; + uint256 tokensDelegatoion = tokens * delegationFeeCut / MAX_PPM; + vm.assume(tokensDataService < tokens - tokensProtocol - tokensDelegatoion); - uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - vm.startPrank(users.verifier); - escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); + vm.assume(delegationTokens > MIN_DELEGATION); + vm.assume(delegationTokens <= MAX_STAKING_TOKENS); + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); - uint256 indexerBalance = token.balanceOf(users.indexer); - uint256 indexerExpectedPayment = amount - tokensDataService - tokensProtocol - tokensDelegatoion; - assertEq(indexerBalance - indexerPreviousBalance, indexerExpectedPayment); - assertEq(token.balanceOf(address(payments)), 0); + resetPrank(users.gateway); + escrow.approveCollector(users.verifier, tokens); + _depositTokens(tokens); + + resetPrank(users.verifier); + _collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, tokens, subgraphDataServiceAddress, tokensDataService); } function testCollect_RevertWhen_CollectorNotAuthorized(uint256 amount) public { @@ -78,4 +156,41 @@ contract GraphEscrowCollectTest is GraphEscrowTest { escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 0); vm.stopPrank(); } + + function testCollect_RevertWhen_InvalidPool( + uint256 amount + ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { + vm.assume(amount > 1 ether); + + resetPrank(users.gateway); + escrow.approveCollector(users.verifier, amount); + _depositTokens(amount); + + resetPrank(users.verifier); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + users.indexer, + subgraphDataServiceAddress + )); + escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 1); + } + + function testCollect_RevertWhen_InvalidProvision( + uint256 amount + ) public useIndexer useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { + vm.assume(amount > 1 ether); + vm.assume(amount <= MAX_STAKING_TOKENS); + + resetPrank(users.gateway); + escrow.approveCollector(users.verifier, amount); + _depositTokens(amount); + + resetPrank(users.verifier); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidProvision.selector, + users.indexer, + subgraphDataServiceAddress + )); + escrow.collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, amount, subgraphDataServiceAddress, 1); + } } \ No newline at end of file diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 62e582c26..8b76678b4 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.27; import "forge-std/Test.sol"; +import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; import { GraphPayments } from "../../contracts/payments/GraphPayments.sol"; @@ -10,6 +11,87 @@ import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStaki contract GraphPaymentsTest is HorizonStakingSharedTest { + struct CollectPaymentData { + uint256 escrowBalance; + uint256 paymentsBalance; + uint256 receiverBalance; + uint256 delegationPoolBalance; + uint256 dataServiceBalance; + } + + function _collect( + IGraphPayments.PaymentTypes _paymentType, + address _receiver, + uint256 _tokens, + address _dataService, + uint256 _tokensDataService + ) private { + // Previous balances + CollectPaymentData memory previousBalances = CollectPaymentData({ + escrowBalance: token.balanceOf(address(escrow)), + paymentsBalance: token.balanceOf(address(payments)), + receiverBalance: token.balanceOf(_receiver), + delegationPoolBalance: staking.getDelegatedTokensAvailable( + _receiver, + _dataService + ), + dataServiceBalance: token.balanceOf(_dataService) + }); + + // Calculate cuts + uint256 protocolPaymentCut = payments.PROTOCOL_PAYMENT_CUT(); + uint256 delegatorCut = staking.getDelegationFeeCut( + _receiver, + _dataService, + _paymentType + ); + uint256 tokensProtocol = _tokens * protocolPaymentCut / MAX_PPM; + uint256 tokensDelegation = _tokens * delegatorCut / MAX_PPM; + + uint256 receiverExpectedPayment = _tokens - _tokensDataService - tokensProtocol - tokensDelegation; + + (,address msgSender, ) = vm.readCallers(); + vm.expectEmit(address(payments)); + emit IGraphPayments.PaymentCollected( + msgSender, + _receiver, + _dataService, + receiverExpectedPayment, + tokensDelegation, + _tokensDataService, + tokensProtocol + ); + payments.collect(_paymentType, _receiver, _tokens, _dataService, _tokensDataService); + + // After balances + CollectPaymentData memory afterBalances = CollectPaymentData({ + escrowBalance: token.balanceOf(address(escrow)), + paymentsBalance: token.balanceOf(address(payments)), + receiverBalance: token.balanceOf(_receiver), + delegationPoolBalance: staking.getDelegatedTokensAvailable( + _receiver, + _dataService + ), + dataServiceBalance: token.balanceOf(_dataService) + }); + + // Check receiver balance after payment + assertEq(afterBalances.receiverBalance - previousBalances.receiverBalance, receiverExpectedPayment); + assertEq(token.balanceOf(address(payments)), 0); + + // Check delegation pool balance after payment + assertEq(afterBalances.delegationPoolBalance - previousBalances.delegationPoolBalance, tokensDelegation); + + // Check that the escrow account has been updated + assertEq(previousBalances.escrowBalance, afterBalances.escrowBalance + _tokens); + + // Check that payments balance didn't change + assertEq(previousBalances.paymentsBalance, afterBalances.paymentsBalance); + + // Check data service balance after payment + assertEq(afterBalances.dataServiceBalance - previousBalances.dataServiceBalance, _tokensDataService); + } + /* * TESTS */ @@ -28,32 +110,28 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { function testCollect( uint256 amount, - uint256 tokensDataService + uint256 tokensDataService, + uint256 tokensDelegate ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { uint256 tokensProtocol = amount * protocolPaymentCut / MAX_PPM; - uint256 tokensDelegatoion = amount * delegationFeeCut / MAX_PPM; - vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegatoion); + uint256 tokensDelegation = amount * delegationFeeCut / MAX_PPM; + vm.assume(tokensDataService < amount - tokensProtocol - tokensDelegation); address escrowAddress = address(escrow); + // Delegate tokens + vm.assume(tokensDelegate > MIN_DELEGATION); + vm.assume(tokensDelegate <= MAX_STAKING_TOKENS); + vm.startPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, tokensDelegate, 0); + // Add tokens in escrow mint(escrowAddress, amount); vm.startPrank(escrowAddress); approve(address(payments), amount); // Collect payments through GraphPayments - uint256 indexerPreviousBalance = token.balanceOf(users.indexer); - payments.collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); + _collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); vm.stopPrank(); - - uint256 indexerBalance = token.balanceOf(users.indexer); - uint256 expectedPayment = amount - tokensDataService - tokensProtocol - tokensDelegatoion; - assertEq(indexerBalance - indexerPreviousBalance, expectedPayment); - - uint256 dataServiceBalance = token.balanceOf(subgraphDataServiceAddress); - assertEq(dataServiceBalance, tokensDataService); - - uint256 delegatorBalance = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(delegatorBalance, tokensDelegatoion); } function testCollect_RevertWhen_InsufficientAmount( @@ -77,4 +155,45 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { vm.expectRevert(expectedError); payments.collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, tokensDataService); } + + function testCollect_RevertWhen_InvalidPool( + uint256 amount + ) public useIndexer useProvision(amount, 0, 0) useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { + vm.assume(amount > 1 ether); + address escrowAddress = address(escrow); + + // Add tokens in escrow + mint(escrowAddress, amount); + vm.startPrank(escrowAddress); + approve(address(payments), amount); + + // Collect payments through GraphPayments + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + users.indexer, + subgraphDataServiceAddress + )); + payments.collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, 1); + } + + function testCollect_RevertWhen_InvalidProvision( + uint256 amount + ) public useIndexer useDelegationFeeCut(IGraphPayments.PaymentTypes.QueryFee, delegationFeeCut) { + vm.assume(amount > 1 ether); + vm.assume(amount <= MAX_STAKING_TOKENS); + address escrowAddress = address(escrow); + + // Add tokens in escrow + mint(escrowAddress, amount); + vm.startPrank(escrowAddress); + approve(address(payments), amount); + + // Collect payments through GraphPayments + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidProvision.selector, + users.indexer, + subgraphDataServiceAddress + )); + payments.collect(IGraphPayments.PaymentTypes.QueryFee, users.indexer, amount, subgraphDataServiceAddress, 1); + } } diff --git a/packages/horizon/test/staking/delegation/addToPool.t.sol b/packages/horizon/test/staking/delegation/addToPool.t.sol index e88becbbf..b9a583ee8 100644 --- a/packages/horizon/test/staking/delegation/addToPool.t.sol +++ b/packages/horizon/test/staking/delegation/addToPool.t.sol @@ -9,6 +9,12 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { modifier useValidDelegationAmount(uint256 tokens) { + vm.assume(tokens > MIN_DELEGATION); + vm.assume(tokens <= MAX_STAKING_TOKENS); + _; + } + + modifier useValidAddToPoolAmount(uint256 tokens) { vm.assume(tokens > 0); vm.assume(tokens <= MAX_STAKING_TOKENS); _; @@ -20,36 +26,31 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { function test_Delegation_AddToPool_Verifier( uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) { - uint256 stakingPreviousBalance = token.balanceOf(address(staking)); - + uint256 delegationAmount, + uint256 addToPoolAmount + ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) useValidAddToPoolAmount(addToPoolAmount) { + // Initialize delegation pool + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); + resetPrank(subgraphDataServiceAddress); - mint(subgraphDataServiceAddress, delegationAmount); - token.approve(address(staking), delegationAmount); - _addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); - - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(delegatedTokens, delegationAmount); - assertEq(token.balanceOf(subgraphDataServiceAddress), 0); - assertEq(token.balanceOf(address(staking)), stakingPreviousBalance + delegationAmount); + mint(subgraphDataServiceAddress, addToPoolAmount); + token.approve(address(staking), addToPoolAmount); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, addToPoolAmount); } function test_Delegation_AddToPool_Payments( uint256 amount, uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) { - uint256 stakingPreviousBalance = token.balanceOf(address(staking)); + ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) useValidAddToPoolAmount(delegationAmount) { + // Initialize delegation pool + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); resetPrank(address(payments)); mint(address(payments), delegationAmount); token.approve(address(staking), delegationAmount); _addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationAmount); - - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(users.indexer, subgraphDataServiceAddress); - assertEq(delegatedTokens, delegationAmount); - assertEq(token.balanceOf(subgraphDataServiceAddress), 0); - assertEq(token.balanceOf(address(staking)), stakingPreviousBalance + delegationAmount); } function test_Delegation_AddToPool_RevertWhen_ZeroTokens( @@ -61,5 +62,29 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 0); } + function test_Delegation_AddToPool_RevertWhen_PoolHasNoShares( + uint256 amount + ) public useIndexer useProvision(amount, 0, 0) { + vm.startPrank(subgraphDataServiceAddress); + bytes memory expectedError = abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + users.indexer, + subgraphDataServiceAddress + ); + vm.expectRevert(expectedError); + staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 1); + } + + function test_Deletaion_AddToPool_RevertWhen_NoProvision() public { + vm.startPrank(subgraphDataServiceAddress); + bytes memory expectedError = abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidProvision.selector, + users.indexer, + subgraphDataServiceAddress + ); + vm.expectRevert(expectedError); + staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 1); + } + // TODO: test recovering an invalid delegation pool } \ No newline at end of file From 76e4940b8203784d06939e70e45b8779ab9464f9 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 12:27:06 +0100 Subject: [PATCH 218/277] fix: update constant names. (OZ N-11) --- .../utilities/ProvisionManager.sol | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index ee5f5e048..0e79bfa47 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -24,12 +24,12 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa using UintRange for uint256; // Constants - uint32 private constant DEFAULT_MIN_UINT32 = 0; - uint64 private constant DEFAULT_MIN_UINT64 = 0; - uint256 private constant DEFAULT_MIN_UINT256 = 0; - uint64 private constant DEFAULT_MAX_UINT64 = type(uint64).max; - uint256 private constant DEFAULT_MAX_UINT256 = type(uint256).max; - uint32 private constant MAX_PPM = uint32(PPMMath.MAX_PPM); + uint32 private constant DEFAULT_MIN_VERIFIER_CUT = 0; + uint64 private constant DEFAULT_MIN_THAWING_PERIOD = 0; + uint256 private constant DEFAULT_MIN_PROVISION_TOKENS = 0; + uint64 private constant DEFAULT_MAX_THAWING_PERIOD = type(uint64).max; + uint256 private constant DEFAULT_MAX_PROVISION_TOKENS = type(uint256).max; + uint32 private constant DEFAULT_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); /** * @notice Emitted when the provision tokens range is set. @@ -123,9 +123,9 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa */ // solhint-disable-next-line func-name-mixedcase function __ProvisionManager_init_unchained() internal onlyInitializing { - _setProvisionTokensRange(DEFAULT_MIN_UINT256, DEFAULT_MAX_UINT256); - _setVerifierCutRange(DEFAULT_MIN_UINT32, MAX_PPM); - _setThawingPeriodRange(DEFAULT_MIN_UINT64, DEFAULT_MAX_UINT64); + _setProvisionTokensRange(DEFAULT_MIN_PROVISION_TOKENS, DEFAULT_MAX_PROVISION_TOKENS); + _setVerifierCutRange(DEFAULT_MIN_VERIFIER_CUT, DEFAULT_MAX_VERIFIER_CUT); + _setThawingPeriodRange(DEFAULT_MIN_THAWING_PERIOD, DEFAULT_MAX_THAWING_PERIOD); } /** From 3bdaec6ffb23810e8b739f314d695e96659780cc Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:38:15 +1000 Subject: [PATCH 219/277] chore: add stakeToFeesRatio to SubgraphService initialize (#1027) * chore: add stakeToFeesRatio to SubgraphService initialize * fix: revert parameter name --- .../contracts/SubgraphService.sol | 16 +++++-- .../contracts/interfaces/ISubgraphService.sol | 5 +++ .../test/SubgraphBaseTest.t.sol | 6 +-- .../subgraphService/SubgraphService.t.sol | 6 +++ .../governance/stakeToFeesRatio.t.sol | 43 +++++++++++++++++++ 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 packages/subgraph-service/test/subgraphService/governance/stakeToFeesRatio.t.sol diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index ce64d9ec0..0b77b277f 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -71,7 +71,11 @@ contract SubgraphService is * @param minimumProvisionTokens The minimum amount of provisioned tokens required to create an allocation * @param maximumDelegationRatio The maximum delegation ratio allowed for an allocation */ - function initialize(uint256 minimumProvisionTokens, uint32 maximumDelegationRatio) external initializer { + function initialize( + uint256 minimumProvisionTokens, + uint32 maximumDelegationRatio, + uint256 stakeToFeesRatio + ) external initializer { __Ownable_init(msg.sender); __DataService_init(); __DataServicePausable_init(); @@ -79,6 +83,7 @@ contract SubgraphService is _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); _setDelegationRatio(maximumDelegationRatio); + _setStakeToFeesRatio(stakeToFeesRatio); } /** @@ -373,8 +378,7 @@ contract SubgraphService is * @notice See {ISubgraphService.setStakeToFeesRatio} */ function setStakeToFeesRatio(uint256 stakeToFeesRatio_) external override onlyOwner { - stakeToFeesRatio = stakeToFeesRatio_; - emit StakeToFeesRatioSet(stakeToFeesRatio_); + _setStakeToFeesRatio(stakeToFeesRatio_); } /** @@ -558,4 +562,10 @@ contract SubgraphService is emit QueryFeesCollected(indexer, tokensCollected, tokensCurators); return tokensCollected; } + + function _setStakeToFeesRatio(uint256 _stakeToFeesRatio) private { + require(_stakeToFeesRatio != 0, SubgraphServiceInvalidZeroStakeToFeesRatio()); + stakeToFeesRatio = _stakeToFeesRatio; + emit StakeToFeesRatioSet(_stakeToFeesRatio); + } } diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index e12554303..b83d672f7 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -122,6 +122,11 @@ interface ISubgraphService is IDataServiceFees { */ error SubgraphServiceAllocationIsAltruistic(address allocationId); + /** + * @notice Thrown when trying to set stake to fees ratio to zero + */ + error SubgraphServiceInvalidZeroStakeToFeesRatio(); + /** * @notice Close a stale allocation * @dev This function can be permissionlessly called when the allocation is stale. diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index d42b66e29..f1aa9b96c 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -151,7 +151,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { address subgraphServiceProxy = UnsafeUpgrades.deployTransparentProxy( subgraphServiceImplementation, users.governor, - abi.encodeCall(SubgraphService.initialize, (minimumProvisionTokens, delegationRatio)) + abi.encodeCall(SubgraphService.initialize, (minimumProvisionTokens, delegationRatio, stakeToFeesRatio)) ); subgraphService = SubgraphService(subgraphServiceProxy); @@ -183,10 +183,10 @@ abstract contract SubgraphBaseTest is Utils, Constants { } function setupProtocol() private { + resetPrank(users.deployer); + subgraphService.transferOwnership(users.governor); resetPrank(users.governor); staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); - resetPrank(users.deployer); - subgraphService.setStakeToFeesRatio(stakeToFeesRatio); subgraphService.setMaxPOIStaleness(maxPOIStaleness); subgraphService.setCurationCut(curationCut); } diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index b5b7f744e..91c486a7b 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -31,6 +31,12 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { * MODIFIERS */ + modifier useGovernor() { + vm.startPrank(users.governor); + _; + vm.stopPrank(); + } + modifier useOperator() { resetPrank(users.indexer); staking.setOperator(users.operator, address(subgraphService), true); diff --git a/packages/subgraph-service/test/subgraphService/governance/stakeToFeesRatio.t.sol b/packages/subgraph-service/test/subgraphService/governance/stakeToFeesRatio.t.sol new file mode 100644 index 000000000..bfd09073e --- /dev/null +++ b/packages/subgraph-service/test/subgraphService/governance/stakeToFeesRatio.t.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol"; +import { SubgraphServiceTest } from "../SubgraphService.t.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +contract DisputeManagerGovernanceArbitratorTest is SubgraphServiceTest { + + /** + * ACTIONS + */ + + function _setStakeToFeesRatio(uint256 _stakeToFeesRatio) internal { + vm.expectEmit(address(subgraphService)); + emit ISubgraphService.StakeToFeesRatioSet(_stakeToFeesRatio); + subgraphService.setStakeToFeesRatio(_stakeToFeesRatio); + assertEq(subgraphService.stakeToFeesRatio(), _stakeToFeesRatio); + } + + /* + * TESTS + */ + + function test_Governance_SetStakeToFeesRatio(uint256 stakeToFeesRatio) public useGovernor { + vm.assume(stakeToFeesRatio > 0); + _setStakeToFeesRatio(stakeToFeesRatio); + } + + function test_Governance_RevertWhen_ZeroValue() public useGovernor { + uint256 stakeToFeesRatio = 0; + vm.expectRevert(abi.encodeWithSelector(ISubgraphService.SubgraphServiceInvalidZeroStakeToFeesRatio.selector)); + subgraphService.setStakeToFeesRatio(stakeToFeesRatio); + } + + function test_Governance_RevertWhen_NotGovernor() public useIndexer { + uint256 stakeToFeesRatio = 2; + vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, users.indexer)); + subgraphService.setStakeToFeesRatio(stakeToFeesRatio); + } +} From 51dd7a8f22b359fa8aaf3820916ca7c40708bd5b Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:38:51 +1000 Subject: [PATCH 220/277] chore(SubgraphService): add Multicall to SubgraphService (#1030) * chore: add Multicall to SubgraphService * fix: add multicall init --- packages/subgraph-service/contracts/SubgraphService.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 0b77b277f..e50762453 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -8,6 +8,7 @@ import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewa import { ISubgraphService } from "./interfaces/ISubgraphService.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { MulticallUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { DataServicePausableUpgradeable } from "@graphprotocol/horizon/contracts/data-service/extensions/DataServicePausableUpgradeable.sol"; import { DataService } from "@graphprotocol/horizon/contracts/data-service/DataService.sol"; @@ -24,6 +25,7 @@ import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; contract SubgraphService is Initializable, OwnableUpgradeable, + MulticallUpgradeable, DataService, DataServicePausableUpgradeable, DataServiceFees, @@ -77,6 +79,7 @@ contract SubgraphService is uint256 stakeToFeesRatio ) external initializer { __Ownable_init(msg.sender); + __Multicall_init(); __DataService_init(); __DataServicePausable_init(); __AllocationManager_init("SubgraphService", "1.0"); From 08539afc31fd3198d8ec7eea716cc935042e5369 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:39:05 +1000 Subject: [PATCH 221/277] fix(SubgraphService): allow collecting rewards when delegation fee cut is 100% (#1038) --- .../contracts/utilities/AllocationManager.sol | 14 ++++++++------ .../collect/indexing/indexing.t.sol | 7 ++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index c555f271c..5bb22cbe2 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -303,12 +303,14 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca // Distribute rewards to indexer tokensIndexerRewards = tokensRewards - tokensDelegationRewards; - address rewardsDestination = rewardsDestination[allocation.indexer]; - if (rewardsDestination == address(0)) { - _graphToken().approve(address(_graphStaking()), tokensIndexerRewards); - _graphStaking().stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); - } else { - _graphToken().pushTokens(rewardsDestination, tokensIndexerRewards); + if (tokensIndexerRewards > 0) { + address rewardsDestination = rewardsDestination[allocation.indexer]; + if (rewardsDestination == address(0)) { + _graphToken().approve(address(_graphStaking()), tokensIndexerRewards); + _graphStaking().stakeToProvision(allocation.indexer, address(this), tokensIndexerRewards); + } else { + _graphToken().pushTokens(rewardsDestination, tokensIndexerRewards); + } } } diff --git a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol index bff35f574..38e9e7865 100644 --- a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol @@ -27,8 +27,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { uint256 delegationTokens, uint256 delegationFeeCut ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { - // Collect reverts if delegationFeeCut is 100% - delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM - 1); + delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM); _setDelegationFeeCut( users.indexer, address(subgraphService), @@ -45,7 +44,6 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { uint256 delegationTokens, uint256 delegationFeeCut ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { - // Collect reverts if delegationFeeCut is 100% delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM); _setDelegationFeeCut( users.indexer, @@ -90,8 +88,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { uint256 delegationTokens, uint256 delegationFeeCut ) public useIndexer useAllocation(tokens) useDelegation(delegationTokens) { - // Collect reverts if delegationFeeCut is 100% - delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM - 1); + delegationFeeCut = bound(delegationFeeCut, 0, MAX_PPM); _setDelegationFeeCut( users.indexer, address(subgraphService), From 3e57ba31739a14ed594cd9ca0b86b1a931605adc Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Sat, 21 Sep 2024 02:22:05 +1000 Subject: [PATCH 222/277] =?UTF-8?q?chore(SubgraphService):=20add=20current?= =?UTF-8?q?=20epoch=20to=20IndexingRewardsCollected=E2=80=A6=20(#1036)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(SubgraphService): add current epoch to IndexingRewardsCollected event * fix: add missing parameter to natspec --- .../contracts/utilities/AllocationManager.sol | 7 ++- .../test/SubgraphBaseTest.t.sol | 6 +- .../test/mocks/MockEpochManager.sol | 63 +++++++++++++++++++ .../subgraphService/SubgraphService.t.sol | 3 +- .../subgraph-service/test/utils/Constants.sol | 3 +- 5 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 packages/subgraph-service/test/mocks/MockEpochManager.sol diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 5bb22cbe2..4ab5fd418 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -57,6 +57,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * @param tokensIndexerRewards The amount of tokens collected for the indexer * @param tokensDelegationRewards The amount of tokens collected for delegators * @param poi The POI presented + * @param currentEpoch The current epoch */ event IndexingRewardsCollected( address indexed indexer, @@ -65,7 +66,8 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca uint256 tokensRewards, uint256 tokensIndexerRewards, uint256 tokensDelegationRewards, - bytes32 poi + bytes32 poi, + uint256 currentEpoch ); /** @@ -321,7 +323,8 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca tokensRewards, tokensIndexerRewards, tokensDelegationRewards, - _poi + _poi, + _graphEpochManager().currentEpoch() ); // Check if the indexer is over-allocated and close the allocation if necessary diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index f1aa9b96c..6ab0c6d24 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -26,6 +26,7 @@ import { Utils } from "./utils/Utils.sol"; import { MockCuration } from "./mocks/MockCuration.sol"; import { MockGRTToken } from "./mocks/MockGRTToken.sol"; import { MockRewardsManager } from "./mocks/MockRewardsManager.sol"; +import { MockEpochManager } from "./mocks/MockEpochManager.sol"; abstract contract SubgraphBaseTest is Utils, Constants { @@ -50,6 +51,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { MockCuration curation; MockGRTToken token; MockRewardsManager rewardsManager; + MockEpochManager epochManager; /* Users */ @@ -91,6 +93,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { GraphProxy stakingProxy = new GraphProxy(address(0), address(proxyAdmin)); rewardsManager = new MockRewardsManager(token, rewardsPerSignal, rewardsPerSubgraphAllocationUpdate); curation = new MockCuration(); + epochManager = new MockEpochManager(); // GraphPayments predict address bytes32 saltGraphPayments = keccak256("GraphPaymentsSalt"); @@ -126,7 +129,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { controller.setContractProxy(keccak256("RewardsManager"), address(rewardsManager)); controller.setContractProxy(keccak256("GraphPayments"), predictedGraphPaymentsAddress); controller.setContractProxy(keccak256("PaymentsEscrow"), predictedEscrowAddress); - controller.setContractProxy(keccak256("EpochManager"), makeAddr("EpochManager")); + controller.setContractProxy(keccak256("EpochManager"), address(epochManager)); controller.setContractProxy(keccak256("GraphTokenGateway"), makeAddr("GraphTokenGateway")); controller.setContractProxy(keccak256("GraphProxyAdmin"), makeAddr("GraphProxyAdmin")); controller.setContractProxy(keccak256("Curation"), address(curation)); @@ -187,6 +190,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { subgraphService.transferOwnership(users.governor); resetPrank(users.governor); staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); + epochManager.setEpochLength(EPOCH_LENGTH); subgraphService.setMaxPOIStaleness(maxPOIStaleness); subgraphService.setCurationCut(curationCut); } diff --git a/packages/subgraph-service/test/mocks/MockEpochManager.sol b/packages/subgraph-service/test/mocks/MockEpochManager.sol new file mode 100644 index 000000000..060a92e21 --- /dev/null +++ b/packages/subgraph-service/test/mocks/MockEpochManager.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.27; + +import { IEpochManager } from "@graphprotocol/contracts/contracts/epochs/IEpochManager.sol"; + +contract MockEpochManager is IEpochManager { + // -- Variables -- + + uint256 public epochLength; + uint256 public lastRunEpoch; + uint256 public lastLengthUpdateEpoch; + uint256 public lastLengthUpdateBlock; + + // -- Configuration -- + + function setEpochLength(uint256 _epochLength) public { + lastLengthUpdateEpoch = 1; + lastLengthUpdateBlock = blockNum(); + epochLength = _epochLength; + } + + // -- Epochs + + function runEpoch() public { + lastRunEpoch = currentEpoch(); + } + + // -- Getters -- + + function isCurrentEpochRun() public view returns (bool) { + return lastRunEpoch == currentEpoch(); + } + + function blockNum() public view returns (uint256) { + return block.number; + } + + function blockHash(uint256 _block) public view returns (bytes32) { + return blockhash(_block); + } + + function currentEpoch() public view returns (uint256) { + return lastLengthUpdateEpoch + epochsSinceUpdate(); + } + + function currentEpochBlock() public view returns (uint256) { + return lastLengthUpdateBlock + (epochsSinceUpdate() * epochLength); + } + + function currentEpochBlockSinceStart() public view returns (uint256) { + return blockNum() - currentEpochBlock(); + } + + function epochsSince(uint256 _epoch) public view returns (uint256) { + uint256 epoch = currentEpoch(); + return _epoch < epoch ? (epoch - _epoch) : 0; + } + + function epochsSinceUpdate() public view returns (uint256) { + return (blockNum() - lastLengthUpdateBlock) / epochLength; + } +} diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 91c486a7b..e62ce8211 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -273,7 +273,8 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { paymentCollected, indexingRewardsData.tokensIndexerRewards, indexingRewardsData.tokensDelegationRewards, - indexingRewardsData.poi + indexingRewardsData.poi, + epochManager.currentEpoch() ); } diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index 1dbfd082e..e70ca8b41 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.27; abstract contract Constants { uint256 internal constant MAX_TOKENS = 10_000_000_000 ether; uint256 internal constant MAX_PPM = 1_000_000; + uint256 internal constant EPOCH_LENGTH = 1; // Dispute Manager uint64 internal constant disputePeriod = 300; // 5 minutes uint256 internal constant disputeDeposit = 100 ether; // 100 GRT @@ -26,4 +27,4 @@ abstract contract Constants { // RewardsMananger parameters uint256 public constant rewardsPerSignal = 10000; uint256 public constant rewardsPerSubgraphAllocationUpdate = 1000; -} \ No newline at end of file +} From 89121252c6aa6a88404cb385bae812d3dbadd071 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 <67825802+MoonBoi9001@users.noreply.github.com> Date: Fri, 20 Sep 2024 19:33:08 +0100 Subject: [PATCH 223/277] Update packages/horizon/contracts/data-service/utilities/ProvisionManager.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomás Migone --- .../contracts/data-service/utilities/ProvisionManager.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 0e79bfa47..8608fd2fa 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -24,12 +24,12 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa using UintRange for uint256; // Constants - uint32 private constant DEFAULT_MIN_VERIFIER_CUT = 0; - uint64 private constant DEFAULT_MIN_THAWING_PERIOD = 0; - uint256 private constant DEFAULT_MIN_PROVISION_TOKENS = 0; + uint32 private constant DEFAULT_MIN_VERIFIER_CUT = type(uint32).min; + uint32 private constant DEFAULT_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); + uint64 private constant DEFAULT_MIN_THAWING_PERIOD = type(uint64).min; uint64 private constant DEFAULT_MAX_THAWING_PERIOD = type(uint64).max; + uint256 private constant DEFAULT_MIN_PROVISION_TOKENS = type(uint256).min; uint256 private constant DEFAULT_MAX_PROVISION_TOKENS = type(uint256).max; - uint32 private constant DEFAULT_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); /** * @notice Emitted when the provision tokens range is set. From cf2109f61d785e323645a86f694329827804391e Mon Sep 17 00:00:00 2001 From: MoonBoi9001 <67825802+MoonBoi9001@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:28:41 +0100 Subject: [PATCH 224/277] fix: remove unused errors, use LegacyAllocationAlreadyMigrated to prevent migrating a legacy allocation twice (OZ N-02) (#1029) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: remove AllocationManagerZeroTokensAllocation. (OZ N-02) * fix: remove DataServiceFeatureNotImplemented. (OZ N-02) * fix: Use LegacyAllocationAlreadyMigrated. (OZ N-02) Use LegacyAllocationAlreadyMigrated to prevent migrating a legacy allocation twice. * fix: restore migrate function to require from if revert. Co-authored-by: Tomás Migone * fix: missing closing braket. --------- Co-authored-by: Tomás Migone --- .../contracts/data-service/interfaces/IDataService.sol | 5 ----- .../contracts/libraries/LegacyAllocation.sol | 5 +++-- .../contracts/utilities/AllocationManager.sol | 10 ++-------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index b7e1028f0..3eec64c04 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -60,11 +60,6 @@ interface IDataService { */ event ServiceProviderSlashed(address indexed serviceProvider, uint256 tokens); - /** - * @notice Thrown to signal that a feature is not implemented by a data service. - */ - error DataServiceFeatureNotImplemented(); - /** * @notice Registers a service provider with the data service. The service provider can now * start providing the service. diff --git a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol index 83bef8037..c60783785 100644 --- a/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol +++ b/packages/subgraph-service/contracts/libraries/LegacyAllocation.sol @@ -39,11 +39,12 @@ library LegacyAllocation { /** * @notice Migrate a legacy allocation * @dev Requirements: - * - The allocation must not exist + * - The allocation must not have been previously migrated * @param self The legacy allocation list mapping * @param indexer The indexer that owns the allocation * @param allocationId The allocation id * @param subgraphDeploymentId The subgraph deployment id the allocation is for + * @custom:error LegacyAllocationAlreadyMigrated if the allocation has already been migrated */ function migrate( mapping(address => State) storage self, @@ -51,7 +52,7 @@ library LegacyAllocation { address allocationId, bytes32 subgraphDeploymentId ) internal { - require(!self[allocationId].exists(), LegacyAllocationExists(allocationId)); + require(!self[allocationId].exists(), LegacyAllocationAlreadyMigrated(allocationId)); State memory allocation = State({ indexer: indexer, subgraphDeploymentId: subgraphDeploymentId }); self[allocationId] = allocation; diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 4ab5fd418..97c3adf99 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -139,13 +139,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca error AllocationManagerInvalidZeroAllocationId(); /** - * @notice Thrown when attempting to create an allocation with zero tokens - * @param allocationId The id of the allocation - */ - error AllocationManagerZeroTokensAllocation(address allocationId); - - /** - * @notice Thrown when attempting to collect indexing rewards on a closed allocation + * @notice Thrown when attempting to collect indexing rewards on a closed allocationl * @param allocationId The id of the allocation */ error AllocationManagerAllocationClosed(address allocationId); @@ -178,7 +172,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca /** * @notice Imports a legacy allocation id into the subgraph service * This is a governor only action that is required to prevent indexers from re-using allocation ids from the - * legacy staking contract. + * legacy staking contract. It will revert with LegacyAllocationAlreadyMigrated if the allocation has already been migrated. * @param _indexer The address of the indexer * @param _allocationId The id of the allocation * @param _subgraphDeploymentId The id of the subgraph deployment From 4ad1ccdf3a6e1229afec0554031cd5fa29fabac9 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 13:04:16 +0100 Subject: [PATCH 225/277] fix: releaseStake n parameter changed to numClaimsToRelease. --- .../data-service/extensions/DataServiceFees.sol | 8 ++++---- .../data-service/interfaces/IDataServiceFees.sol | 4 ++-- .../data-service/extensions/DataServiceFees.t.sol | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index e0ea587f4..83ebbe971 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -22,8 +22,8 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat /** * @notice See {IDataServiceFees-releaseStake} */ - function releaseStake(uint256 n) external virtual override { - _releaseStake(msg.sender, n); + function releaseStake(uint256 numClaimsToRelease) external virtual override { + _releaseStake(msg.sender, numClaimsToRelease); } /** @@ -61,14 +61,14 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat /** * @notice See {IDataServiceFees-releaseStake} */ - function _releaseStake(address _serviceProvider, uint256 _n) internal { + function _releaseStake(address _serviceProvider, uint256 _numClaimsToRelease) internal { LinkedList.List storage claimsList = claimsLists[_serviceProvider]; (uint256 claimsReleased, bytes memory data) = claimsList.traverse( _getNextStakeClaim, _processStakeClaim, _deleteStakeClaim, abi.encode(0, _serviceProvider), - _n + _numClaimsToRelease ); emit StakeClaimsReleased(_serviceProvider, claimsReleased, abi.decode(data, (uint256))); diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index 483f11274..2677f247e 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -89,7 +89,7 @@ interface IDataServiceFees is IDataService { * stake claims that releasing them all at once would exceed the block gas limit. * @dev This function can be overriden and/or disabled. * @dev Emits a {StakeClaimsReleased} event, and a {StakeClaimReleased} event for each claim released. - * @param n Amount of stake claims to process. If 0, all stake claims are processed. + * @param numClaimsToRelease Amount of stake claims to process. If 0, all stake claims are processed. */ - function releaseStake(uint256 n) external; + function releaseStake(uint256 numClaimsToRelease) external; } diff --git a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol index f6f31d54c..fef08d094 100644 --- a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol @@ -81,14 +81,14 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { function test_Release_WhenNIsValid( uint256 tokens, uint256 steps, - uint256 n + uint256 numClaimsToRelease ) external useIndexer useProvisionDataService(address(dataService), PROVISION_TOKENS, 0, 0) { // lock all provisioned stake in steps // limit tokens to at least 1 per step // limit steps to at least 15 so we stagger locks every 5 seconds to have some expired tokens = bound(tokens, 50, PROVISION_TOKENS / dataService.STAKE_TO_FEES_RATIO()); steps = bound(steps, 15, 50); - n = bound(n, 0, steps); + numClaimsToRelease = bound(numClaimsToRelease, 0, steps); uint256 stepAmount = tokens / steps; @@ -99,7 +99,7 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { } // it should release all expired claims - _assert_releaseStake(users.indexer, n); + _assert_releaseStake(users.indexer, numClaimsToRelease); } function test_Release_WhenNIsNotValid( @@ -180,7 +180,7 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { uint256 tokensReleased; bytes32 head; } - function _assert_releaseStake(address serviceProvider, uint256 n) private { + function _assert_releaseStake(address serviceProvider, uint256 numClaimsToRelease) private { // before state (bytes32 beforeHead, bytes32 beforeTail, uint256 beforeNonce, uint256 beforeCount) = dataService.claimsLists( serviceProvider @@ -195,7 +195,7 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { tokensReleased: 0, head: beforeHead }); - while (calcValues.head != bytes32(0) && (calcValues.claimsCount < n || n == 0)) { + while (calcValues.head != bytes32(0) && (calcValues.claimsCount < numClaimsToRelease || numClaimsToRelease == 0)) { (uint256 claimTokens, , uint256 releaseAt, bytes32 nextClaim) = dataService.claims(calcValues.head); if (releaseAt > block.timestamp) { break; @@ -209,7 +209,7 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { // it should emit a an event emit IDataServiceFees.StakeClaimsReleased(serviceProvider, calcValues.claimsCount, calcValues.tokensReleased); - dataService.releaseStake(n); + dataService.releaseStake(numClaimsToRelease); // after state (bytes32 afterHead, bytes32 afterTail, uint256 afterNonce, uint256 afterCount) = dataService.claimsLists( From d90b971a19639589f6f6a440edfd4dc3737ddff1 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 13:09:06 +0100 Subject: [PATCH 226/277] fix: function _setPartialPaused(bool _toPause) chnaged to function _setPartialPaused(bool _toPartialPause). --- packages/contracts/contracts/governance/Controller.sol | 6 +++--- packages/contracts/contracts/governance/Pausable.sol | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index 2b71fd885..707a27fff 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -89,10 +89,10 @@ contract Controller is Governed, Pausable, IController { /** * @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 + * @param _toPartialPause True if the contracts should be (partially) paused, false otherwise */ - function setPartialPaused(bool _toPause) external override onlyGovernorOrGuardian { - _setPartialPaused(_toPause); + function setPartialPaused(bool _toPartialPause) external override onlyGovernorOrGuardian { + _setPartialPaused(_toPartialPause); } /** diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 6c5d2fd2c..179762527 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -31,13 +31,13 @@ abstract contract Pausable { /** * @dev 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) + * @param _toPartialPause New value for the partial pause state (true means the contracts will be partially paused) */ - function _setPartialPaused(bool _toPause) internal { - if (_toPause == _partialPaused) { + function _setPartialPaused(bool _toPartialPause) internal { + if (_toPartialPause == _partialPaused) { return; } - _partialPaused = _toPause; + _partialPaused = _toPartialPause; if (_partialPaused) { lastPausePartialTime = block.timestamp; } From 9d819efaa308b1aef5a44b0dc302f525396cd3bd Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 13:11:19 +0100 Subject: [PATCH 227/277] fix: lastPausePartialTime now lastPartialPauseTime.. --- packages/contracts/contracts/governance/Pausable.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts/contracts/governance/Pausable.sol b/packages/contracts/contracts/governance/Pausable.sol index 179762527..2bc1795cd 100644 --- a/packages/contracts/contracts/governance/Pausable.sol +++ b/packages/contracts/contracts/governance/Pausable.sol @@ -14,7 +14,7 @@ abstract contract Pausable { bool internal _paused; /// Timestamp for the last time the partial pause was set - uint256 public lastPausePartialTime; + uint256 public lastPartialPauseTime; /// Timestamp for the last time the full pause was set uint256 public lastPauseTime; @@ -39,7 +39,7 @@ abstract contract Pausable { } _partialPaused = _toPartialPause; if (_partialPaused) { - lastPausePartialTime = block.timestamp; + lastPartialPauseTime = block.timestamp; } emit PartialPauseChanged(_partialPaused); } From 2d69d2a9eff23403fd7531108c6b25b29285e2f2 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 15:57:36 +0100 Subject: [PATCH 228/277] fix: acceptProvision updated to acceptProvisionPendingParameters --- .../contracts/data-service/interfaces/IDataService.sol | 2 +- .../test/data-service/implementations/DataServiceBase.sol | 2 +- .../implementations/DataServiceBaseUpgradeable.sol | 2 +- .../data-service/implementations/DataServiceImpFees.sol | 2 +- .../implementations/DataServiceImpPausable.sol | 2 +- .../implementations/DataServiceImpPausableUpgradeable.sol | 2 +- packages/subgraph-service/contracts/SubgraphService.sol | 4 ++-- .../test/subgraphService/SubgraphService.t.sol | 2 +- .../test/subgraphService/provision/accept.t.sol | 8 ++++---- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index 3eec64c04..61d032e68 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -88,7 +88,7 @@ interface IDataService { * @param serviceProvider The address of the service provider. * @param data Custom data, usage defined by the data service. */ - function acceptProvision(address serviceProvider, bytes calldata data) external; + function acceptProvisionPendingParameters(address serviceProvider, bytes calldata data) external; /** * @notice Service provider starts providing the service. diff --git a/packages/horizon/test/data-service/implementations/DataServiceBase.sol b/packages/horizon/test/data-service/implementations/DataServiceBase.sol index d98dd2857..0d51241ce 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceBase.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBase.sol @@ -19,7 +19,7 @@ contract DataServiceBase is DataService { function register(address serviceProvider, bytes calldata data) external {} - function acceptProvision(address serviceProvider, bytes calldata data) external {} + function acceptProvisionPendingParameters(address serviceProvider, bytes calldata data) external {} function startService(address serviceProvider, bytes calldata data) external {} diff --git a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol index 31309c524..a7ebfd465 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceBaseUpgradeable.sol @@ -15,7 +15,7 @@ contract DataServiceBaseUpgradeable is DataService { function register(address serviceProvider, bytes calldata data) external {} - function acceptProvision(address serviceProvider, bytes calldata data) external {} + function acceptProvisionPendingParameters(address serviceProvider, bytes calldata data) external {} function startService(address serviceProvider, bytes calldata data) external {} diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol index efabda6ff..ac5c79c89 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpFees.sol @@ -15,7 +15,7 @@ contract DataServiceImpFees is DataServiceFees { function register(address serviceProvider, bytes calldata data) external {} - function acceptProvision(address serviceProvider, bytes calldata data) external {} + function acceptProvisionPendingParameters(address serviceProvider, bytes calldata data) external {} function startService(address serviceProvider, bytes calldata data) external {} diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol index 0ca990ab1..5073207ab 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausable.sol @@ -23,7 +23,7 @@ contract DataServiceImpPausable is DataServicePausable { function register(address serviceProvider, bytes calldata data) external {} - function acceptProvision(address serviceProvider, bytes calldata data) external {} + function acceptProvisionPendingParameters(address serviceProvider, bytes calldata data) external {} function startService(address serviceProvider, bytes calldata data) external {} diff --git a/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol index 39b2bb26b..cea615885 100644 --- a/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol +++ b/packages/horizon/test/data-service/implementations/DataServiceImpPausableUpgradeable.sol @@ -17,7 +17,7 @@ contract DataServiceImpPausableUpgradeable is DataServicePausableUpgradeable { function register(address serviceProvider, bytes calldata data) external {} - function acceptProvision(address serviceProvider, bytes calldata data) external {} + function acceptProvisionPendingParameters(address serviceProvider, bytes calldata data) external {} function startService(address serviceProvider, bytes calldata data) external {} diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index e50762453..18148faf8 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -131,7 +131,7 @@ contract SubgraphService is /** * @notice Accept staged parameters in the provision of a service provider - * @dev Implements {IDataService-acceptProvision} + * @dev Implements {IDataService-acceptProvisionPendingParameters} * * Requirements: * - The indexer must be registered @@ -142,7 +142,7 @@ contract SubgraphService is * * @param indexer The address of the indexer to accept the provision for */ - function acceptProvision( + function acceptProvisionPendingParameters( address indexer, bytes calldata ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index e62ce8211..1f441a9c3 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -86,7 +86,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { emit IDataService.ProvisionAccepted(_indexer); // Accept provision - subgraphService.acceptProvision(_indexer, _data); + subgraphService.acceptProvisionPendingParameters(_indexer, _data); // Update provision after acceptance provision = staking.getProvision(_indexer, address(subgraphService)); diff --git a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol index 1c8191275..44ce19b5f 100644 --- a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol +++ b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol @@ -40,7 +40,7 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { ISubgraphService.SubgraphServiceIndexerNotRegistered.selector, users.indexer )); - subgraphService.acceptProvision(users.indexer, ""); + subgraphService.acceptProvisionPendingParameters(users.indexer, ""); } function test_SubgraphService_Provision_Accept_RevertWhen_NotAuthorized() public { @@ -50,7 +50,7 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { users.operator, users.indexer )); - subgraphService.acceptProvision(users.indexer, ""); + subgraphService.acceptProvisionPendingParameters(users.indexer, ""); } function test_SubgraphService_Provision_Accept_RevertIf_InvalidVerifierCut( @@ -75,7 +75,7 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { fishermanRewardPercentage, MAX_PPM )); - subgraphService.acceptProvision(users.indexer, ""); + subgraphService.acceptProvisionPendingParameters(users.indexer, ""); } function test_SubgraphService_Provision_Accept_RevertIf_InvalidDisputePeriod( @@ -100,6 +100,6 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { disputePeriod, type(uint64).max )); - subgraphService.acceptProvision(users.indexer, ""); + subgraphService.acceptProvisionPendingParameters(users.indexer, ""); } } From a4ba0ab5cf0648117e3f329b54beba5f92c0b670 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 15:58:45 +0100 Subject: [PATCH 229/277] fix: rename staged to pending. --- .../horizon/contracts/data-service/interfaces/IDataService.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index 61d032e68..b3f168bbe 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -79,7 +79,7 @@ interface IDataService { function register(address serviceProvider, bytes calldata data) external; /** - * @notice Accepts staged parameters in the provision of a service provider in the {Graph Horizon staking + * @notice Accepts pending parameters in the provision of a service provider in the {Graph Horizon staking * contract}. * @dev Provides a way for the data service to validate and accept provision parameter changes. Call {_acceptProvision}. * From 76bedb3ed5fc88536d98f7b7fb9d62705f511dfa Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 16:38:55 +0100 Subject: [PATCH 230/277] fix: rename maxVerifierCut to newMaxVerifierCut and thawingPeriod to newThawingPeriod. --- .../horizon/contracts/staking/HorizonStaking.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index c8709e639..8d74df83e 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -226,16 +226,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { function setProvisionParameters( address serviceProvider, address verifier, - uint32 maxVerifierCut, - uint64 thawingPeriod + uint32 newMaxVerifierCut, + uint64 newThawingPeriod ) external override notPaused onlyAuthorized(serviceProvider, verifier) { Provision storage prov = _provisions[serviceProvider][verifier]; require(prov.createdAt != 0, HorizonStakingInvalidProvision(serviceProvider, verifier)); - if ((prov.maxVerifierCutPending != maxVerifierCut) || (prov.thawingPeriodPending != thawingPeriod)) { - prov.maxVerifierCutPending = maxVerifierCut; - prov.thawingPeriodPending = thawingPeriod; - emit ProvisionParametersStaged(serviceProvider, verifier, maxVerifierCut, thawingPeriod); + if ((prov.maxVerifierCutPending != newMaxVerifierCut) || (prov.thawingPeriodPending != newThawingPeriod)) { + prov.maxVerifierCutPending = newMaxVerifierCut; + prov.thawingPeriodPending = newThawingPeriod; + emit ProvisionParametersStaged(serviceProvider, verifier, newMaxVerifierCut, newThawingPeriod); } } From faafe8267fb0a2cb88be2e156134b738bf8d57dc Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 18:56:09 +0100 Subject: [PATCH 231/277] fix: onlyProvisionAuthorized now onlyAuthorizedForProvision. --- .../data-service/utilities/ProvisionManager.sol | 2 +- .../subgraph-service/contracts/SubgraphService.sol | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index d1cf94287..fbd3936ac 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -82,7 +82,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa /** * @notice Checks if the caller is authorized to manage the provision of a service provider. */ - modifier onlyProvisionAuthorized(address serviceProvider) { + modifier onlyAuthorizedForProvision(address serviceProvider) { require( _graphStaking().isAuthorized(msg.sender, serviceProvider, address(this)), ProvisionManagerNotAuthorized(msg.sender, serviceProvider) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 18148faf8..793b05623 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -110,7 +110,7 @@ contract SubgraphService is function register( address indexer, bytes calldata data - ) external override onlyProvisionAuthorized(indexer) onlyValidProvision(indexer) whenNotPaused { + ) external override onlyAuthorizedForProvision(indexer) onlyValidProvision(indexer) whenNotPaused { (string memory url, string memory geohash, address rewardsDestination) = abi.decode( data, (string, string, address) @@ -145,7 +145,7 @@ contract SubgraphService is function acceptProvisionPendingParameters( address indexer, bytes calldata - ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + ) external override onlyAuthorizedForProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { _checkProvisionTokens(indexer); _acceptProvisionParameters(indexer); emit ProvisionAccepted(indexer); @@ -181,7 +181,7 @@ contract SubgraphService is ) external override - onlyProvisionAuthorized(indexer) + onlyAuthorizedForProvision(indexer) onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused @@ -216,7 +216,7 @@ contract SubgraphService is function stopService( address indexer, bytes calldata data - ) external override onlyProvisionAuthorized(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { + ) external override onlyAuthorizedForProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { address allocationId = abi.decode(data, (address)); require( allocations.get(allocationId).indexer == indexer, @@ -254,7 +254,7 @@ contract SubgraphService is ) external override - onlyProvisionAuthorized(indexer) + onlyAuthorizedForProvision(indexer) onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused @@ -326,7 +326,7 @@ contract SubgraphService is uint256 tokens ) external - onlyProvisionAuthorized(indexer) + onlyAuthorizedForProvision(indexer) onlyValidProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused From e73cb44777ca5f09f0f08a63cb77b19ea7c0d97b Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 18:56:48 +0100 Subject: [PATCH 232/277] fix: ProvisionAccepted now ProvisionPendingParametersAccepted. --- .../contracts/data-service/interfaces/IDataService.sol | 4 ++-- .../contracts/data-service/utilities/ProvisionManager.sol | 2 +- packages/subgraph-service/contracts/SubgraphService.sol | 4 ++-- .../test/subgraphService/SubgraphService.t.sol | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/horizon/contracts/data-service/interfaces/IDataService.sol b/packages/horizon/contracts/data-service/interfaces/IDataService.sol index b3f168bbe..7770bc9a5 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataService.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataService.sol @@ -25,7 +25,7 @@ interface IDataService { * @notice Emitted when a service provider accepts a provision in {Graph Horizon staking contract}. * @param serviceProvider The address of the service provider. */ - event ProvisionAccepted(address indexed serviceProvider); + event ProvisionPendingParametersAccepted(address indexed serviceProvider); /** * @notice Emitted when a service provider starts providing the service. @@ -83,7 +83,7 @@ interface IDataService { * contract}. * @dev Provides a way for the data service to validate and accept provision parameter changes. Call {_acceptProvision}. * - * Emits a {ProvisionAccepted} event. + * Emits a {ProvisionPendingParametersAccepted} event. * * @param serviceProvider The address of the service provider. * @param data Custom data, usage defined by the data service. diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index fbd3936ac..3670fcdbd 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -125,7 +125,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * the {HorizonStaking} contract. * @dev Checks the pending provision parameters, not the current ones. * - * Emits a {ProvisionAccepted} event. + * Emits a {ProvisionPendingParametersAccepted} event. * * @param _serviceProvider The address of the service provider. */ diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 793b05623..a4f6375dd 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -138,7 +138,7 @@ contract SubgraphService is * - Must have previously staged provision parameters, using {IHorizonStaking-setProvisionParameters} * - The new provision parameters must be valid according to the subgraph service rules * - * Emits a {ProvisionAccepted} event + * Emits a {ProvisionPendingParametersAccepted} event * * @param indexer The address of the indexer to accept the provision for */ @@ -148,7 +148,7 @@ contract SubgraphService is ) external override onlyAuthorizedForProvision(indexer) onlyRegisteredIndexer(indexer) whenNotPaused { _checkProvisionTokens(indexer); _acceptProvisionParameters(indexer); - emit ProvisionAccepted(indexer); + emit ProvisionPendingParametersAccepted(indexer); } /** diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 1f441a9c3..67338fe64 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -83,7 +83,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { uint64 thawingPeriodPending = provision.thawingPeriodPending; vm.expectEmit(address(subgraphService)); - emit IDataService.ProvisionAccepted(_indexer); + emit IDataService.ProvisionPendingParametersAccepted(_indexer); // Accept provision subgraphService.acceptProvisionPendingParameters(_indexer, _data); From 69e1971b199af9f67426779f3dfbfc7de8107493 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 19:02:52 +0100 Subject: [PATCH 233/277] fix: releaseAt updated to releasableAt --- .../data-service/extensions/DataServiceFees.sol | 6 +++--- .../data-service/interfaces/IDataServiceFees.sol | 6 +++--- .../test/data-service/extensions/DataServiceFees.t.sol | 10 +++++----- .../test/subgraphService/SubgraphService.t.sol | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol index 83ebbe971..09102dd4a 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceFees.sol @@ -49,7 +49,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat claims[claimId] = StakeClaim({ tokens: _tokens, createdAt: block.timestamp, - releaseAt: _unlockTimestamp, + releasableAt: _unlockTimestamp, nextClaim: bytes32(0) }); if (claimsList.count != 0) claims[claimsList.tail].nextClaim = claimId; @@ -86,7 +86,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat StakeClaim memory claim = _getStakeClaim(_claimId); // early exit - if (claim.releaseAt > block.timestamp) { + if (claim.releasableAt > block.timestamp) { return (true, LinkedList.NULL_BYTES); } @@ -95,7 +95,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat // process feesProvisionTracker.release(serviceProvider, claim.tokens); - emit StakeClaimReleased(serviceProvider, _claimId, claim.tokens, claim.releaseAt); + emit StakeClaimReleased(serviceProvider, _claimId, claim.tokens, claim.releasableAt); // encode _acc = abi.encode(tokensClaimed + claim.tokens, serviceProvider); diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol index 2677f247e..c94fc6e00 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceFees.sol @@ -32,7 +32,7 @@ interface IDataServiceFees is IDataService { // Timestamp when the claim was created uint256 createdAt; // Timestamp when the claim will expire and tokens can be released - uint256 releaseAt; + uint256 releasableAt; // Next claim in the linked list bytes32 nextClaim; } @@ -56,13 +56,13 @@ interface IDataServiceFees is IDataService { * @param serviceProvider The address of the service provider * @param claimId The id of the stake claim * @param tokens The amount of tokens released - * @param releaseAt The timestamp when the tokens were released + * @param releasableAt The timestamp when the tokens were released */ event StakeClaimReleased( address indexed serviceProvider, bytes32 indexed claimId, uint256 tokens, - uint256 releaseAt + uint256 releasableAt ); /** diff --git a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol index fef08d094..a45a7bee2 100644 --- a/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol +++ b/packages/horizon/test/data-service/extensions/DataServiceFees.t.sol @@ -159,12 +159,12 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { assertEq(beforeLockedStake + calcValues.stakeToLock, afterLockedStake); // it should create a stake claim - (uint256 claimTokens, uint256 createdAt, uint256 releaseAt, bytes32 nextClaim) = dataService.claims( + (uint256 claimTokens, uint256 createdAt, uint256 releasableAt, bytes32 nextClaim) = dataService.claims( calcValues.predictedClaimId ); assertEq(claimTokens, calcValues.stakeToLock); assertEq(createdAt, block.timestamp); - assertEq(releaseAt, calcValues.unlockTimestamp); + assertEq(releasableAt, calcValues.unlockTimestamp); assertEq(nextClaim, bytes32(0)); // it should update the list @@ -196,12 +196,12 @@ contract DataServiceFeesTest is HorizonStakingSharedTest { head: beforeHead }); while (calcValues.head != bytes32(0) && (calcValues.claimsCount < numClaimsToRelease || numClaimsToRelease == 0)) { - (uint256 claimTokens, , uint256 releaseAt, bytes32 nextClaim) = dataService.claims(calcValues.head); - if (releaseAt > block.timestamp) { + (uint256 claimTokens, , uint256 releasableAt, bytes32 nextClaim) = dataService.claims(calcValues.head); + if (releasableAt > block.timestamp) { break; } - emit IDataServiceFees.StakeClaimReleased(serviceProvider, calcValues.head, claimTokens, releaseAt); + emit IDataServiceFees.StakeClaimReleased(serviceProvider, calcValues.head, claimTokens, releasableAt); calcValues.head = nextClaim; calcValues.tokensReleased += claimTokens; calcValues.claimsCount++; diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 67338fe64..a5563176b 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -328,7 +328,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { uint64 disputePeriod = disputeManager.getDisputePeriod(); assertEq(stakeClaim.tokens, tokensToLock); assertEq(stakeClaim.createdAt, block.timestamp); - assertEq(stakeClaim.releaseAt, block.timestamp + disputePeriod); + assertEq(stakeClaim.releasableAt, block.timestamp + disputePeriod); assertEq(stakeClaim.nextClaim, bytes32(0)); } else if (_paymentType == IGraphPayments.PaymentTypes.IndexingRewards) { // Update allocation after collecting rewards @@ -419,7 +419,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { } function _getStakeClaim(bytes32 _claimId) private view returns (IDataServiceFees.StakeClaim memory) { - (uint256 tokens, uint256 createdAt, uint256 releaseAt, bytes32 nextClaim) = subgraphService.claims(_claimId); - return IDataServiceFees.StakeClaim(tokens, createdAt, releaseAt, nextClaim); + (uint256 tokens, uint256 createdAt, uint256 releasableAt, bytes32 nextClaim) = subgraphService.claims(_claimId); + return IDataServiceFees.StakeClaim(tokens, createdAt, releasableAt, nextClaim); } } From 78821abd2428fd94a25a361dcae6e9dfcf06c9b1 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 19:04:03 +0100 Subject: [PATCH 234/277] fix: "Resolve the conflicting dispute" updated to "Draw the conflicting dispute". --- packages/contracts/contracts/disputes/DisputeManager.sol | 2 +- packages/subgraph-service/contracts/DisputeManager.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts/contracts/disputes/DisputeManager.sol b/packages/contracts/contracts/disputes/DisputeManager.sol index 6700ec341..53bf43b1e 100644 --- a/packages/contracts/contracts/disputes/DisputeManager.sol +++ b/packages/contracts/contracts/disputes/DisputeManager.sol @@ -606,7 +606,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Resolve the conflicting dispute if there is any for the one passed to this function. + * @dev Draw the conflicting dispute if there is any for the one passed to this function. * @param _dispute Dispute * @return True if resolved */ diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 8bf0f363b..f7e6be9ab 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -560,7 +560,7 @@ contract DisputeManager is } /** - * @notice Resolve the conflicting dispute if there is any for the one passed to this function. + * @notice Draw the conflicting dispute if there is any for the one passed to this function. * @param _dispute Dispute * @return True if resolved */ From 99d9bba0ffaaacac162364b0f8bf6e71e8a9856c Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 19:27:16 +0100 Subject: [PATCH 235/277] fix: MAX_THAWING_PERIOD rename to MAX_WAIT_PERIOD in PaymentsEscrow and Constants --- .../horizon/contracts/interfaces/IPaymentsEscrow.sol | 4 ++-- packages/horizon/contracts/payments/PaymentsEscrow.sol | 10 +++++----- packages/subgraph-service/test/SubgraphBaseTest.t.sol | 2 +- packages/subgraph-service/test/utils/Constants.sol | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 4b98cf0a5..47d5c8308 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -131,9 +131,9 @@ interface IPaymentsEscrow { /** * @notice Thrown when setting the thawing period to a value greater than the maximum * @param thawingPeriod The thawing period - * @param maxThawingPeriod The maximum thawing period + * @param maxWaitPeriod The maximum wait period */ - error PaymentsEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxThawingPeriod); + error PaymentsEscrowThawingPeriodTooLong(uint256 thawingPeriod, uint256 maxWaitPeriod); /** * @notice Thrown when a collector has insufficient allowance to collect funds diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 5d0694346..b96bb56be 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -31,7 +31,7 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, /// @notice The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation /// @dev This is a precautionary measure to avoid inadvertedly locking funds for too long - uint256 public constant MAX_THAWING_PERIOD = 90 days; + uint256 public constant MAX_WAIT_PERIOD = 90 days; /// @notice Thawing period in seconds for authorized collectors uint256 public immutable REVOKE_COLLECTOR_THAWING_PERIOD; @@ -56,12 +56,12 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, uint256 withdrawEscrowThawingPeriod ) GraphDirectory(controller) { require( - revokeCollectorThawingPeriod <= MAX_THAWING_PERIOD, - PaymentsEscrowThawingPeriodTooLong(revokeCollectorThawingPeriod, MAX_THAWING_PERIOD) + revokeCollectorThawingPeriod <= MAX_WAIT_PERIOD, + PaymentsEscrowThawingPeriodTooLong(revokeCollectorThawingPeriod, MAX_WAIT_PERIOD) ); require( - withdrawEscrowThawingPeriod <= MAX_THAWING_PERIOD, - PaymentsEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_THAWING_PERIOD) + withdrawEscrowThawingPeriod <= MAX_WAIT_PERIOD, + PaymentsEscrowThawingPeriodTooLong(withdrawEscrowThawingPeriod, MAX_WAIT_PERIOD) ); REVOKE_COLLECTOR_THAWING_PERIOD = revokeCollectorThawingPeriod; diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 6ab0c6d24..43065add6 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -189,7 +189,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { resetPrank(users.deployer); subgraphService.transferOwnership(users.governor); resetPrank(users.governor); - staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); + staking.setMaxThawingPeriod(MAX_WAIT_PERIOD); epochManager.setEpochLength(EPOCH_LENGTH); subgraphService.setMaxPOIStaleness(maxPOIStaleness); subgraphService.setCurationCut(curationCut); diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index e70ca8b41..eabf5e7b2 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -18,7 +18,7 @@ abstract contract Constants { uint256 public constant maxPOIStaleness = 28 days; uint256 public constant curationCut = 10000; // Staking - uint64 internal constant MAX_THAWING_PERIOD = 28 days; + uint64 internal constant MAX_WAIT_PERIOD = 28 days; // GraphEscrow parameters uint256 internal constant withdrawEscrowThawingPeriod = 60; uint256 internal constant revokeCollectorThawingPeriod = 60; From 9503f1dc054c9b4ee80611b7721bc7b9a4a04491 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 20 Sep 2024 19:29:55 +0100 Subject: [PATCH 236/277] fix: challenger and submitter updated to fisherman. --- .../contracts/disputes/DisputeManager.sol | 30 ++++++++--------- .../contracts/test/unit/disputes/common.ts | 4 +-- .../contracts/DisputeManager.sol | 32 +++++++++---------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/contracts/contracts/disputes/DisputeManager.sol b/packages/contracts/contracts/disputes/DisputeManager.sol index 53bf43b1e..fed301de0 100644 --- a/packages/contracts/contracts/disputes/DisputeManager.sol +++ b/packages/contracts/contracts/disputes/DisputeManager.sol @@ -29,7 +29,7 @@ import "./IDisputeManager.sol"; * Indexers present a Proof of Indexing (POI) when they close allocations to prove * they were indexing a subgraph. The Staking contract emits that proof with the format * keccak256(indexer.address, POI). - * Any challenger can dispute the validity of a POI by submitting a dispute to this contract + * Any fisherman can dispute the validity of a POI by submitting a dispute to this contract * along with a deposit. * * Arbitration: @@ -355,8 +355,8 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _deposit Amount of tokens staked as deposit */ function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) external override returns (bytes32) { - // Get funds from submitter - _pullSubmitterDeposit(_deposit); + // Get funds from fisherman + _pullFishermanDeposit(_deposit); // Create a dispute return @@ -372,7 +372,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 + * For this type of dispute the fisherman 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. @@ -470,14 +470,14 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa /** * @dev Create an indexing dispute for the arbitrator to resolve. * The disputes are created in reference to an allocationID - * This function is called by a challenger that will need to `_deposit` at + * This function is called by a fisherman that will need to `_deposit` at * least `minimumDeposit` GRT tokens. * @param _allocationID The allocation to dispute * @param _deposit Amount of tokens staked as deposit */ function createIndexingDispute(address _allocationID, uint256 _deposit) external override returns (bytes32) { - // Get funds from submitter - _pullSubmitterDeposit(_deposit); + // Get funds from fisherman + _pullFishermanDeposit(_deposit); // Create a dispute return _createIndexingDisputeWithAllocation(msg.sender, _deposit, _allocationID); @@ -485,7 +485,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa /** * @dev Create indexing dispute internal function. - * @param _fisherman The challenger creating the dispute + * @param _fisherman The fisherman creating the dispute * @param _deposit Amount of tokens staked as deposit * @param _allocationID Allocation disputed */ @@ -621,10 +621,10 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Pull deposit from submitter account. + * @dev Pull deposit from fisherman account. * @param _deposit Amount of tokens to deposit */ - function _pullSubmitterDeposit(uint256 _deposit) private { + function _pullFishermanDeposit(uint256 _deposit) private { // Ensure that fisherman has staked at least the minimum amount require(_deposit >= minimumDeposit, "Dispute deposit is under minimum required"); @@ -633,17 +633,17 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Make the staking contract slash the indexer and reward the challenger. - * Give the challenger a reward equal to the fishermanRewardPercentage of slashed amount + * @dev Make the staking contract slash the indexer and reward the fisherman. + * Give the fisherman a reward equal to the fishermanRewardPercentage of slashed amount * @param _indexer Address of the indexer - * @param _challenger Address of the challenger + * @param _fisherman Address of the fisherman * @param _disputeType Type of dispute * @return slashAmount Dispute slash amount * @return rewardsAmount Dispute rewards amount */ function _slashIndexer( address _indexer, - address _challenger, + address _fisherman, DisputeType _disputeType ) private returns (uint256 slashAmount, uint256 rewardsAmount) { IStaking staking = staking(); @@ -660,7 +660,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa // Have staking contract slash the indexer and reward the fisherman // Give the fisherman a reward equal to the fishermanRewardPercentage of slashed amount - staking.slash(_indexer, slashAmount, rewardsAmount, _challenger); + staking.slash(_indexer, slashAmount, rewardsAmount, _fisherman); } /** diff --git a/packages/contracts/test/unit/disputes/common.ts b/packages/contracts/test/unit/disputes/common.ts index 37d77fd5a..f72f3c6cf 100644 --- a/packages/contracts/test/unit/disputes/common.ts +++ b/packages/contracts/test/unit/disputes/common.ts @@ -16,7 +16,7 @@ export interface Dispute { export function createQueryDisputeID( attestation: Attestation, indexerAddress: string, - submitterAddress: string, + fishermanAddress: string, ): string { return solidityKeccak256( ['bytes32', 'bytes32', 'bytes32', 'address', 'address'], @@ -25,7 +25,7 @@ export function createQueryDisputeID( attestation.responseCID, attestation.subgraphDeploymentID, indexerAddress, - submitterAddress, + fishermanAddress, ], ) } diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index f7e6be9ab..d900e6cf1 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -34,7 +34,7 @@ import { AttestationManager } from "./utilities/AttestationManager.sol"; * Indexers present a Proof of Indexing (POI) when they close allocations to prove * they were indexing a subgraph. The Staking contract emits that proof with the format * keccak256(indexer.address, POI). - * Any challenger can dispute the validity of a POI by submitting a dispute to this contract + * Any fisherman can dispute the validity of a POI by submitting a dispute to this contract * along with a deposit. * * Arbitration: @@ -127,18 +127,18 @@ contract DisputeManager is * @notice Create an indexing dispute for the arbitrator to resolve. * The disputes are created in reference to an allocationId and specifically * a POI for that allocation. - * This function is called by a challenger and it will pull `disputeDeposit` GRT tokens. + * This function is called by a fisherman and it will pull `disputeDeposit` GRT tokens. * * Requirements: - * - Challenger must have previously approved this contract to pull `disputeDeposit` amount + * - fisherman must have previously approved this contract to pull `disputeDeposit` amount * of tokens from their balance. * * @param allocationId The allocation to dispute * @param poi The Proof of Indexing (POI) being disputed */ function createIndexingDispute(address allocationId, bytes32 poi) external override returns (bytes32) { - // Get funds from submitter - _pullSubmitterDeposit(); + // Get funds from fisherman + _pullFishermanDeposit(); // Create a dispute return _createIndexingDisputeWithAllocation(msg.sender, disputeDeposit, allocationId, poi); @@ -146,17 +146,17 @@ contract DisputeManager is /** * @notice Create a query dispute for the arbitrator to resolve. - * This function is called by a challenger and it will pull `disputeDeposit` GRT tokens. + * This function is called by a fisherman and it will pull `disputeDeposit` GRT tokens. * * * Requirements: - * - Challenger must have previously approved this contract to pull `disputeDeposit` amount + * - fisherman must have previously approved this contract to pull `disputeDeposit` amount * of tokens from their balance. * - * @param attestationData Attestation bytes submitted by the challenger + * @param attestationData Attestation bytes submitted by the fisherman */ function createQueryDispute(bytes calldata attestationData) external override returns (bytes32) { - // Get funds from submitter - _pullSubmitterDeposit(); + // Get funds from fisherman + _pullFishermanDeposit(); // Create a dispute return @@ -172,7 +172,7 @@ contract DisputeManager is * @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 + * For this type of dispute the fisherman 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. @@ -515,7 +515,7 @@ contract DisputeManager is /** * @notice Create indexing dispute internal function. - * @param _fisherman The challenger creating the dispute + * @param _fisherman The fisherman creating the dispute * @param _deposit Amount of tokens staked as deposit * @param _allocationId Allocation disputed * @param _poi The POI being disputed @@ -590,16 +590,16 @@ contract DisputeManager is } /** - * @notice Pull `disputeDeposit` from submitter account. + * @notice Pull `disputeDeposit` from fisherman account. */ - function _pullSubmitterDeposit() private { + function _pullFishermanDeposit() private { // Transfer tokens to deposit from fisherman to this contract _graphToken().pullTokens(msg.sender, disputeDeposit); } /** - * @notice Make the subgraph service contract slash the indexer and reward the challenger. - * Give the challenger a reward equal to the fishermanRewardPercentage of slashed amount + * @notice Make the subgraph service contract slash the indexer and reward the fisherman. + * Give the fisherman a reward equal to the fishermanRewardPercentage of slashed amount * @param _indexer Address of the indexer * @param _tokensSlash Amount of tokens to slash from the indexer * @param _tokensStakeSnapshot Snapshot of the indexer's stake at the time of the dispute creation From 2729a376ac0be6386bcd7d02ea39e74d5cb4fc32 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Mon, 30 Sep 2024 15:44:50 +0100 Subject: [PATCH 237/277] fix: use new constants in subgraphservice.sol --- .../data-service/utilities/ProvisionManager.sol | 6 +++--- .../subgraph-service/contracts/SubgraphService.sol | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 8608fd2fa..b5c905ad5 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -25,11 +25,11 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa // Constants uint32 private constant DEFAULT_MIN_VERIFIER_CUT = type(uint32).min; - uint32 private constant DEFAULT_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); + uint32 internal constant DEFAULT_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); uint64 private constant DEFAULT_MIN_THAWING_PERIOD = type(uint64).min; - uint64 private constant DEFAULT_MAX_THAWING_PERIOD = type(uint64).max; + uint64 internal constant DEFAULT_MAX_THAWING_PERIOD = type(uint64).max; uint256 private constant DEFAULT_MIN_PROVISION_TOKENS = type(uint256).min; - uint256 private constant DEFAULT_MAX_PROVISION_TOKENS = type(uint256).max; + uint256 internal constant DEFAULT_MAX_PROVISION_TOKENS = type(uint256).max; /** * @notice Emitted when the provision tokens range is set. diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 5023e6160..909aa7750 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -21,9 +21,14 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; +import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; + + + contract SubgraphService is Initializable, OwnableUpgradeable, + ProvisionManager, DataService, DataServicePausableUpgradeable, DataServiceFees, @@ -359,7 +364,7 @@ contract SubgraphService is * @notice See {ISubgraphService.setMinimumProvisionTokens} */ function setMinimumProvisionTokens(uint256 minimumProvisionTokens) external override onlyOwner { - _setProvisionTokensRange(minimumProvisionTokens, type(uint256).max); + _setProvisionTokensRange(minimumProvisionTokens, DEFAULT_MAX_PROVISION_TOKENS); } /** @@ -473,7 +478,7 @@ contract SubgraphService is */ function _getThawingPeriodRange() internal view override returns (uint64 min, uint64 max) { uint64 disputePeriod = _disputeManager().getDisputePeriod(); - return (disputePeriod, type(uint64).max); + return (disputePeriod, DEFAULT_MAX_THAWING_PERIOD); } /** @@ -483,7 +488,7 @@ contract SubgraphService is */ function _getVerifierCutRange() internal view override returns (uint32 min, uint32 max) { uint32 verifierCut = _disputeManager().getVerifierCut(); - return (verifierCut, uint32(PPMMath.MAX_PPM)); + return (verifierCut, DEFAULT_MAX_VERIFIER_CUT); } /** From aa27c54a1b176b17a2334b40582645bb4860ed61 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Mon, 30 Sep 2024 17:56:02 +0100 Subject: [PATCH 238/277] fix: emit amount authorized + rescuded token in AuthorizedCollector/TokensRescued respectively. --- .../contracts/data-service/extensions/DataServiceRescuable.sol | 2 +- .../data-service/interfaces/IDataServiceRescuable.sol | 2 +- packages/horizon/contracts/interfaces/IPaymentsEscrow.sol | 3 ++- packages/horizon/contracts/payments/PaymentsEscrow.sol | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol index 081950b8d..0d2f0750d 100644 --- a/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/extensions/DataServiceRescuable.sol @@ -70,6 +70,6 @@ abstract contract DataServiceRescuable is DataService, IDataServiceRescuable { if (Denominations.isNativeToken(_token)) Address.sendValue(payable(_to), _tokens); else SafeERC20.safeTransfer(IERC20(_token), _to, _tokens); - emit TokensRescued(msg.sender, _to, _tokens); + emit TokensRescued(msg.sender, _to, _token, _tokens); } } diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index 811d3b92e..07e97ee8c 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -12,7 +12,7 @@ interface IDataServiceRescuable is IDataService { /** * @notice Emitted when tokens are rescued from the contract. */ - event TokensRescued(address indexed from, address indexed to, uint256 tokens); + event TokensRescued(address indexed from, address indexed to, address token, uint256 tokens); /** * @notice Emitted when a rescuer is set. diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 4b98cf0a5..40394900f 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -38,8 +38,9 @@ interface IPaymentsEscrow { * @notice Emitted when a payer authorizes a collector to collect funds * @param payer The address of the payer * @param collector The address of the collector + * @param allowance The number of tokens the collector is allowed to collect */ - event AuthorizedCollector(address indexed payer, address indexed collector); + event AuthorizedCollector(address indexed payer, address indexed collector, uint256 allowance); /** * @notice Emitted when a payer thaws a collector diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 5d0694346..4b76e2bc6 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -82,7 +82,7 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, require(allowance != 0, PaymentsEscrowInvalidZeroTokens()); Collector storage collector = authorizedCollectors[msg.sender][collector_]; collector.allowance += allowance; - emit AuthorizedCollector(msg.sender, collector_); + emit AuthorizedCollector(msg.sender, collector_, collector.allowance); } /** From 8ce493f79e179a6cdd35b9f12c3f8f74056852f3 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 12:49:04 +0100 Subject: [PATCH 239/277] fix: direct bugs to new security contact email address. --- packages/horizon/contracts/payments/GraphPayments.sol | 3 ++- packages/horizon/contracts/payments/PaymentsEscrow.sol | 3 ++- .../horizon/contracts/payments/collectors/TAPCollector.sol | 3 ++- packages/horizon/contracts/staking/HorizonStaking.sol | 3 ++- packages/horizon/contracts/staking/HorizonStakingExtension.sol | 3 ++- packages/subgraph-service/contracts/DisputeManager.sol | 3 ++- packages/subgraph-service/contracts/SubgraphService.sol | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/horizon/contracts/payments/GraphPayments.sol b/packages/horizon/contracts/payments/GraphPayments.sol index ea3063d81..c621f62dc 100644 --- a/packages/horizon/contracts/payments/GraphPayments.sol +++ b/packages/horizon/contracts/payments/GraphPayments.sol @@ -16,7 +16,8 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; * @notice This contract is part of the Graph Horizon payments protocol. It's designed * to pull funds (GRT) from the {PaymentsEscrow} and distribute them according to a * set of pre established rules. - * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + * @custom:security-contact Please email security+contracts@thegraph.com if you find any + * bugs. We may have an active bug bounty program. */ contract GraphPayments is Initializable, MulticallUpgradeable, GraphDirectory, IGraphPayments { using TokenUtils for IGraphToken; diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index c7c4e72e5..46736ec3e 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -17,7 +17,8 @@ import { GraphDirectory } from "../utilities/GraphDirectory.sol"; * @notice This contract is part of the Graph Horizon payments protocol. It holds the funds (GRT) * for payments made through the payments protocol for services provided * via a Graph Horizon data service. - * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + * @custom:security-contact Please email security+contracts@thegraph.com if you find any + * bugs. We may have an active bug bounty program. */ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, IPaymentsEscrow { using TokenUtils for IGraphToken; diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index fe96b78f3..f9b228ead 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -17,7 +17,8 @@ import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; * @dev Note that the contract expects the RAV aggregate value to be monotonically increasing, each successive RAV for the same * (data service-payer-receiver) tuple should have a value greater than the previous one. The contract will keep track of the tokens * already collected and calculate the difference to collect. - * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + * @custom:security-contact Please email security+contracts@thegraph.com if you find any + * bugs. We may have an active bug bounty program. */ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { using PPMMath for uint256; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index ea64fccda..6a5479878 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -24,7 +24,8 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * This is due to the contract size limit on Arbitrum (24kB). The extension contract implements functionality to support * the legacy staking functions and the transfer tools. Both can be eventually removed without affecting the main * staking contract. - * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + * @custom:security-contact Please email security+contracts@thegraph.com if you find any + * bugs. We may have an active bug bounty program. */ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { using TokenUtils for IGraphToken; diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index c6e6f5607..cbb70cc20 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -24,7 +24,8 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * without losing rewards or having service interruptions. * @dev TODO: Once the transition period and the transfer tools are deemed not necessary this contract * can be removed. It's expected the transition period to last for a full allocation cycle (28 epochs). - * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + * @custom:security-contact Please email security+contracts@thegraph.com if you find any + * bugs. We may have an active bug bounty program. */ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizonStakingExtension { using TokenUtils for IGraphToken; diff --git a/packages/subgraph-service/contracts/DisputeManager.sol b/packages/subgraph-service/contracts/DisputeManager.sol index 7bc932782..ce3685948 100644 --- a/packages/subgraph-service/contracts/DisputeManager.sol +++ b/packages/subgraph-service/contracts/DisputeManager.sol @@ -40,7 +40,8 @@ import { AttestationManager } from "./utilities/AttestationManager.sol"; * Arbitration: * Disputes can only be accepted, rejected or drawn by the arbitrator role that can be delegated * to a EOA or DAO. - * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + * @custom:security-contact Please email security+contracts@thegraph.com if you find any + * bugs. We may have an active bug bounty program. */ contract DisputeManager is Initializable, diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 0d2676476..b2b43da40 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -23,7 +23,8 @@ import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; /** * @title SubgraphService contract - * @custom:security-contact Bug bounty program: https://immunefi.com/bug-bounty/thegraph/information/ + * @custom:security-contact Please email security+contracts@thegraph.com if you find any + * bugs. We may have an active bug bounty program. */ contract SubgraphService is Initializable, From b721f7254cad577bedb5f7a12495c634e7f7b1df Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 13:41:51 +0100 Subject: [PATCH 240/277] fix: set _verifyAllocationProof visability private. --- .../subgraph-service/contracts/utilities/AllocationManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 97c3adf99..00a323b9a 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -465,7 +465,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca * @param _allocationId The id of the allocation * @param _proof The EIP712 proof, an EIP712 signed message of (indexer,allocationId) */ - function _verifyAllocationProof(address _indexer, address _allocationId, bytes memory _proof) internal view { + function _verifyAllocationProof(address _indexer, address _allocationId, bytes memory _proof) private view { bytes32 digest = _encodeAllocationProof(_indexer, _allocationId); address signer = ECDSA.recover(digest, _proof); require(signer == _allocationId, AllocationManagerInvalidAllocationProof(signer, _allocationId)); From fbc6654d755e0ec96a019bf49a47f39c223125b6 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 13:42:26 +0100 Subject: [PATCH 241/277] fix: set _getDelegatedTokensAvailable visability private. --- packages/horizon/contracts/staking/HorizonStakingBase.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index b55b39fd8..d9fb613c3 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -290,7 +290,7 @@ abstract contract HorizonStakingBase is /** * @notice See {IHorizonStakingBase-getDelegatedTokensAvailable}. */ - function _getDelegatedTokensAvailable(address _serviceProvider, address _verifier) internal view returns (uint256) { + function _getDelegatedTokensAvailable(address _serviceProvider, address _verifier) private view returns (uint256) { DelegationPoolInternal storage poolInternal = _getDelegationPool(_serviceProvider, _verifier); return poolInternal.tokens - poolInternal.tokensThawing; } From decde7fbf38d25d42b671c8a6a07aa966c4467e9 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 13:44:05 +0100 Subject: [PATCH 242/277] fix: set _receiveIndexerStake _receiveDelegation visability private. --- .../horizon/contracts/staking/HorizonStakingExtension.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index 66efe5521..d81e707b9 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -326,7 +326,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon function _receiveIndexerStake( uint256 _tokens, IL2StakingTypes.ReceiveIndexerStakeData memory _indexerData - ) internal { + ) private { address indexer = _indexerData.indexer; // Deposit tokens into the indexer stake _stake(indexer, _tokens); @@ -345,7 +345,7 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon function _receiveDelegation( uint256 _tokens, IL2StakingTypes.ReceiveDelegationData memory _delegationData - ) internal { + ) private { require(_provisions[_delegationData.indexer][SUBGRAPH_DATA_SERVICE_ADDRESS].createdAt != 0, "!provision"); // Get the delegation pool of the indexer DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; From b5d3a7d379b65ceaa841fccd760d2a7763537009 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 13:44:57 +0100 Subject: [PATCH 243/277] fix: set _deposit visability private. --- packages/horizon/contracts/payments/PaymentsEscrow.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 5d0694346..756546c47 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -232,7 +232,7 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, * @param _receiver The address of the receiver * @param _tokens The amount of tokens to deposit */ - function _deposit(address _payer, address _receiver, uint256 _tokens) internal { + function _deposit(address _payer, address _receiver, uint256 _tokens) private { escrowAccounts[_payer][_receiver].balance += _tokens; _graphToken().pullTokens(msg.sender, _tokens); emit Deposit(_payer, _receiver, _tokens); From 32b39657bb2b462ac4c02068dba688318788ce65 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 13:47:26 +0100 Subject: [PATCH 244/277] fix: set drawDispute visability external. --- packages/contracts/contracts/disputes/DisputeManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/contracts/disputes/DisputeManager.sol b/packages/contracts/contracts/disputes/DisputeManager.sol index 6700ec341..013a21b03 100644 --- a/packages/contracts/contracts/disputes/DisputeManager.sol +++ b/packages/contracts/contracts/disputes/DisputeManager.sol @@ -579,7 +579,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @notice Ignore a dispute with ID `_disputeID` * @param _disputeID ID of the dispute to be disregarded */ - function drawDispute(bytes32 _disputeID) public override onlyArbitrator onlyPendingDispute(_disputeID) { + function drawDispute(bytes32 _disputeID) external override onlyArbitrator onlyPendingDispute(_disputeID) { Dispute storage dispute = disputes[_disputeID]; // Return deposit to the fisherman From 96b5c3c1eef410fec4dbc6e3ef673fdae267b7d5 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Mon, 30 Sep 2024 18:32:18 +0100 Subject: [PATCH 245/277] fix: emit both amount authorized and total authorized commit to now emit both the amount for which the collector was authorized and also the total amount for which they are now authorized --- .../data-service/interfaces/IDataServiceRescuable.sol | 4 ++++ .../horizon/contracts/interfaces/IPaymentsEscrow.sol | 10 ++++++++-- packages/horizon/contracts/payments/PaymentsEscrow.sol | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index 07e97ee8c..67026f2d4 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -11,6 +11,10 @@ import { IDataService } from "./IDataService.sol"; interface IDataServiceRescuable is IDataService { /** * @notice Emitted when tokens are rescued from the contract. + * @param from The address initiating the rescue + * @param to The address receiving the rescued tokens + * @param token The address of the token being rescued + * @param tokens The amount of tokens rescued */ event TokensRescued(address indexed from, address indexed to, address token, uint256 tokens); diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index 40394900f..cae2558e7 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -38,9 +38,15 @@ interface IPaymentsEscrow { * @notice Emitted when a payer authorizes a collector to collect funds * @param payer The address of the payer * @param collector The address of the collector - * @param allowance The number of tokens the collector is allowed to collect + * @param addedAllowance The amount of tokens added to the collector's allowance + * @param newTotalAllowance The new total allowance after addition */ - event AuthorizedCollector(address indexed payer, address indexed collector, uint256 allowance); + event AuthorizedCollector( + address indexed payer, + address indexed collector, + uint256 addedAllowance, + uint256 newTotalAllowance + ); /** * @notice Emitted when a payer thaws a collector diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index 4b76e2bc6..0c775cd47 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -82,7 +82,7 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, require(allowance != 0, PaymentsEscrowInvalidZeroTokens()); Collector storage collector = authorizedCollectors[msg.sender][collector_]; collector.allowance += allowance; - emit AuthorizedCollector(msg.sender, collector_, collector.allowance); + emit AuthorizedCollector(msg.sender, collector_, allowance, collector.allowance); } /** From a598eca7e6ab93252d10197b8b0ea4228b39c7b8 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 17:20:03 +0100 Subject: [PATCH 246/277] fix: set all ProvisionManager constants internal. --- .../contracts/data-service/utilities/ProvisionManager.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index b5c905ad5..1af1a28b4 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -24,11 +24,11 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa using UintRange for uint256; // Constants - uint32 private constant DEFAULT_MIN_VERIFIER_CUT = type(uint32).min; + uint32 internal constant DEFAULT_MIN_VERIFIER_CUT = type(uint32).min; uint32 internal constant DEFAULT_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); - uint64 private constant DEFAULT_MIN_THAWING_PERIOD = type(uint64).min; + uint64 internal constant DEFAULT_MIN_THAWING_PERIOD = type(uint64).min; uint64 internal constant DEFAULT_MAX_THAWING_PERIOD = type(uint64).max; - uint256 private constant DEFAULT_MIN_PROVISION_TOKENS = type(uint256).min; + uint256 internal constant DEFAULT_MIN_PROVISION_TOKENS = type(uint256).min; uint256 internal constant DEFAULT_MAX_PROVISION_TOKENS = type(uint256).max; /** From de6c82214254106fbb354186e6b5981a58bd59cd Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 17:21:30 +0100 Subject: [PATCH 247/277] fix: remove ProvisionManager inheritance. --- packages/subgraph-service/contracts/SubgraphService.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 098307ceb..a928c0b0f 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -22,14 +22,12 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; -import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; contract SubgraphService is Initializable, OwnableUpgradeable, - ProvisionManager, MulticallUpgradeable, DataService, DataServicePausableUpgradeable, From ffd1f79c1ec9b397de64be6ef8e7d3714b575ae0 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Tue, 1 Oct 2024 17:26:10 +0100 Subject: [PATCH 248/277] fix: remove whitespace. --- packages/subgraph-service/contracts/SubgraphService.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index a928c0b0f..b4d1b3f4a 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -22,9 +22,6 @@ import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol" import { Allocation } from "./libraries/Allocation.sol"; import { LegacyAllocation } from "./libraries/LegacyAllocation.sol"; - - - contract SubgraphService is Initializable, OwnableUpgradeable, From f86b12a28f7810fb7a0e66da9b889306f09cb207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 1 Oct 2024 14:49:01 -0300 Subject: [PATCH 249/277] feat(horizon): deploy horizon with Hardhat Ignition (#1025) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(horizon): wip ignition deployment * feat: add ignition modules for horizon contracts Signed-off-by: Tomás Migone * feat: add deploy scripts for horizon staking contracts Signed-off-by: Tomás Migone * feat: first version of horizon contracts deployed with ignition Signed-off-by: Tomás Migone * feat: deploy subgraph service using ignition Signed-off-by: Tomás Migone * fix: remove deployment files for localhost Signed-off-by: Tomás Migone * chore: gitignore localhost deployment files for ignition Signed-off-by: Tomás Migone * chore: add deployment files for arbitrum sepolia and sepolia Signed-off-by: Tomás Migone * fix: deployment tweaks, add deployment files to github Signed-off-by: Tomás Migone * fix: use correct network name for arbitrum sepolia Signed-off-by: Tomás Migone * fix: hardhat build Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone --- .gitignore | 4 + packages/horizon/README.md | 22 +- packages/horizon/contracts/mocks/Dummy.sol | 5 + packages/horizon/hardhat.config.ts | 29 + .../ignition/configs/horizon.hardhat.json | 46 + .../artifacts/BridgeEscrow#BridgeEscrow.json | 159 ++ .../BridgeEscrow#BridgeEscrow_Instance.json | 159 ++ .../artifacts/BridgeEscrow#GraphProxy.json | 177 ++ .../artifacts/Controller#Controller.json | 349 +++ .../artifacts/Curation#Curation.json | 707 +++++ .../artifacts/Curation#Curation_Instance.json | 707 +++++ .../Curation#GraphCurationToken.json | 414 +++ .../artifacts/Curation#GraphProxy.json | 177 ++ .../artifacts/EpochManager#EpochManager.json | 364 +++ .../EpochManager#EpochManager_Instance.json | 364 +++ .../artifacts/EpochManager#GraphProxy.json | 177 ++ .../GraphHorizon_Periphery#Dummy.json | 10 + .../GraphPayments#GraphPayments.json | 308 +++ .../GraphPayments#GraphPayments_Instance.json | 308 +++ .../GraphProxyAdmin#GraphProxyAdmin.json | 234 ++ .../artifacts/GraphToken#GraphProxy.json | 177 ++ .../artifacts/GraphToken#GraphToken.json | 750 ++++++ .../GraphToken#GraphToken_Instance.json | 750 ++++++ .../GraphTokenGateway#GraphProxy.json | 177 ++ .../GraphTokenGateway#GraphTokenGateway.json | 647 +++++ ...kenGateway#GraphTokenGateway_Instance.json | 647 +++++ ...izonProxies#GraphProxy_HorizonStaking.json | 177 ++ ...zonProxies#OZProxyDummy_GraphPayments.json | 10 + ...onProxies#OZProxyDummy_PaymentsEscrow.json | 10 + ...rizonProxies#ProxyAdmin_GraphPayments.json | 132 + ...izonProxies#ProxyAdmin_PaymentsEscrow.json | 132 + .../HorizonProxies#RegisteredDummy.json | 10 + ...sparentUpgradeableProxy_GraphPayments.json | 116 + ...parentUpgradeableProxy_PaymentsEscrow.json | 116 + .../HorizonStaking#HorizonStaking.json | 2280 +++++++++++++++++ ...orizonStaking#HorizonStaking_Instance.json | 2280 +++++++++++++++++ ...onStakingExtension#ExponentialRebates.json | 55 + ...kingExtension#HorizonStakingExtension.json | 1263 +++++++++ .../PaymentsEscrow#PaymentsEscrow.json | 769 ++++++ ...aymentsEscrow#PaymentsEscrow_Instance.json | 769 ++++++ .../artifacts/RewardsManager#GraphProxy.json | 177 ++ .../RewardsManager#RewardsManager.json | 635 +++++ ...ewardsManager#RewardsManager_Instance.json | 635 +++++ .../artifacts/TAPCollector#TAPCollector.json | 450 ++++ .../chain-11155111/deployed_addresses.json | 41 + .../deployments/chain-11155111/journal.jsonl | 318 +++ .../artifacts/BridgeEscrow#BridgeEscrow.json | 159 ++ .../BridgeEscrow#BridgeEscrow_Instance.json | 159 ++ .../artifacts/BridgeEscrow#GraphProxy.json | 177 ++ .../artifacts/Controller#Controller.json | 349 +++ .../artifacts/Curation#Curation.json | 707 +++++ .../artifacts/Curation#Curation_Instance.json | 707 +++++ .../Curation#GraphCurationToken.json | 414 +++ .../artifacts/Curation#GraphProxy.json | 177 ++ .../artifacts/EpochManager#EpochManager.json | 364 +++ .../EpochManager#EpochManager_Instance.json | 364 +++ .../artifacts/EpochManager#GraphProxy.json | 177 ++ .../GraphHorizon_Periphery#Dummy.json | 10 + .../GraphPayments#GraphPayments.json | 308 +++ .../GraphPayments#GraphPayments_Instance.json | 308 +++ .../GraphProxyAdmin#GraphProxyAdmin.json | 234 ++ .../artifacts/GraphToken#GraphProxy.json | 177 ++ .../artifacts/GraphToken#GraphToken.json | 750 ++++++ .../GraphToken#GraphToken_Instance.json | 750 ++++++ .../GraphTokenGateway#GraphProxy.json | 177 ++ .../GraphTokenGateway#GraphTokenGateway.json | 647 +++++ ...kenGateway#GraphTokenGateway_Instance.json | 647 +++++ ...izonProxies#GraphProxy_HorizonStaking.json | 177 ++ ...zonProxies#OZProxyDummy_GraphPayments.json | 10 + ...onProxies#OZProxyDummy_PaymentsEscrow.json | 10 + ...rizonProxies#ProxyAdmin_GraphPayments.json | 132 + ...izonProxies#ProxyAdmin_PaymentsEscrow.json | 132 + .../HorizonProxies#RegisteredDummy.json | 10 + ...sparentUpgradeableProxy_GraphPayments.json | 116 + ...parentUpgradeableProxy_PaymentsEscrow.json | 116 + .../HorizonStaking#HorizonStaking.json | 2280 +++++++++++++++++ ...orizonStaking#HorizonStaking_Instance.json | 2280 +++++++++++++++++ ...onStakingExtension#ExponentialRebates.json | 55 + ...kingExtension#HorizonStakingExtension.json | 1263 +++++++++ .../PaymentsEscrow#PaymentsEscrow.json | 769 ++++++ ...aymentsEscrow#PaymentsEscrow_Instance.json | 769 ++++++ .../artifacts/RewardsManager#GraphProxy.json | 177 ++ .../RewardsManager#RewardsManager.json | 635 +++++ ...ewardsManager#RewardsManager_Instance.json | 635 +++++ .../artifacts/TAPCollector#TAPCollector.json | 450 ++++ .../chain-421614/deployed_addresses.json | 41 + .../deployments/chain-421614/journal.jsonl | 328 +++ packages/horizon/ignition/modules/core.ts | 15 + .../ignition/modules/core/GraphPayments.ts | 31 + .../ignition/modules/core/HorizonProxies.ts | 42 + .../ignition/modules/core/HorizonStaking.ts | 38 + .../modules/core/HorizonStakingExtension.ts | 26 + .../ignition/modules/core/PaymentsEscrow.ts | 32 + .../ignition/modules/core/TAPCollector.ts | 18 + packages/horizon/ignition/modules/horizon.ts | 31 + .../horizon/ignition/modules/periphery.ts | 57 + .../modules/periphery/BridgeEscrow.ts | 18 + .../ignition/modules/periphery/Controller.ts | 17 + .../ignition/modules/periphery/Curation.ts | 23 + .../modules/periphery/EpochManager.ts | 19 + .../modules/periphery/GraphProxyAdmin.ts | 13 + .../ignition/modules/periphery/GraphToken.ts | 33 + .../modules/periphery/GraphTokenGateway.ts | 22 + .../modules/periphery/RewardsManager.ts | 26 + .../ignition/modules/proxy/GraphProxy.ts | 36 + .../proxy/TransparentUpgradeableProxy.ts | 33 + packages/horizon/package.json | 13 +- packages/horizon/scripts/deploy.ts | 16 + packages/horizon/tsconfig.json | 1 + packages/subgraph-service/hardhat.config.ts | 2 +- .../configs/subgraph-service.hardhat.json | 13 + .../ignition/modules/DisputeManager.ts | 36 + .../ignition/modules/Proxies.ts | 10 + .../ignition/modules/SubgraphService.ts | 34 + packages/subgraph-service/package.json | 9 +- packages/subgraph-service/scripts/deploy.ts | 117 +- packages/subgraph-service/tsconfig.json | 5 +- yarn.lock | 234 +- 118 files changed, 37341 insertions(+), 69 deletions(-) create mode 100644 packages/horizon/contracts/mocks/Dummy.sol create mode 100644 packages/horizon/ignition/configs/horizon.hardhat.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/Controller#Controller.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphCurationToken.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphHorizon_Periphery#Dummy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphProxyAdmin#GraphProxyAdmin.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#RegisteredDummy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#ExponentialRebates.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#HorizonStakingExtension.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/artifacts/TAPCollector#TAPCollector.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/deployed_addresses.json create mode 100644 packages/horizon/ignition/deployments/chain-11155111/journal.jsonl create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/Controller#Controller.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphCurationToken.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphHorizon_Periphery#Dummy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphProxyAdmin#GraphProxyAdmin.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#RegisteredDummy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#ExponentialRebates.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#HorizonStakingExtension.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#GraphProxy.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager_Instance.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/artifacts/TAPCollector#TAPCollector.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/deployed_addresses.json create mode 100644 packages/horizon/ignition/deployments/chain-421614/journal.jsonl create mode 100644 packages/horizon/ignition/modules/core.ts create mode 100644 packages/horizon/ignition/modules/core/GraphPayments.ts create mode 100644 packages/horizon/ignition/modules/core/HorizonProxies.ts create mode 100644 packages/horizon/ignition/modules/core/HorizonStaking.ts create mode 100644 packages/horizon/ignition/modules/core/HorizonStakingExtension.ts create mode 100644 packages/horizon/ignition/modules/core/PaymentsEscrow.ts create mode 100644 packages/horizon/ignition/modules/core/TAPCollector.ts create mode 100644 packages/horizon/ignition/modules/horizon.ts create mode 100644 packages/horizon/ignition/modules/periphery.ts create mode 100644 packages/horizon/ignition/modules/periphery/BridgeEscrow.ts create mode 100644 packages/horizon/ignition/modules/periphery/Controller.ts create mode 100644 packages/horizon/ignition/modules/periphery/Curation.ts create mode 100644 packages/horizon/ignition/modules/periphery/EpochManager.ts create mode 100644 packages/horizon/ignition/modules/periphery/GraphProxyAdmin.ts create mode 100644 packages/horizon/ignition/modules/periphery/GraphToken.ts create mode 100644 packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts create mode 100644 packages/horizon/ignition/modules/periphery/RewardsManager.ts create mode 100644 packages/horizon/ignition/modules/proxy/GraphProxy.ts create mode 100644 packages/horizon/ignition/modules/proxy/TransparentUpgradeableProxy.ts create mode 100644 packages/horizon/scripts/deploy.ts create mode 100644 packages/subgraph-service/ignition/configs/subgraph-service.hardhat.json create mode 100644 packages/subgraph-service/ignition/modules/DisputeManager.ts create mode 100644 packages/subgraph-service/ignition/modules/Proxies.ts create mode 100644 packages/subgraph-service/ignition/modules/SubgraphService.ts diff --git a/.gitignore b/.gitignore index 55602edb4..01a1de8c7 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,7 @@ cache_forge tx-builder-*.json !tx-builder-template.json + +# Hardhat Ignition +**/chain-31337/ +!**/ignition/**/artifacts/ diff --git a/packages/horizon/README.md b/packages/horizon/README.md index 7be82e5d6..d3a0d6200 100644 --- a/packages/horizon/README.md +++ b/packages/horizon/README.md @@ -1,13 +1,17 @@ -# Sample Hardhat Project +# 🌅 Graph Horizon 🌅 -This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract. +Graph Horizon is the next evolution of the Graph Protocol. -Try running some of the following tasks: +## Deployment -```shell -npx hardhat help -npx hardhat test -REPORT_GAS=true npx hardhat test -npx hardhat node -npx hardhat run scripts/deploy.ts +We use Hardhat Ignition to deploy the contracts. To build and deploy the contracts run the following commands: + +```bash +yarn install +yarn build +npx hardhat ignition deploy ./ignition/modules/horizon.ts \ + --parameters ./ignition/configs/graph.hardhat.json \ + --network hardhat ``` + +You can use any network defined in `hardhat.config.ts` by replacing `hardhat` with the network name. \ No newline at end of file diff --git a/packages/horizon/contracts/mocks/Dummy.sol b/packages/horizon/contracts/mocks/Dummy.sol new file mode 100644 index 000000000..e6a575d0f --- /dev/null +++ b/packages/horizon/contracts/mocks/Dummy.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity 0.8.27; + +contract Dummy {} diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index de221c723..57f1d8f89 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -1,5 +1,6 @@ import '@nomicfoundation/hardhat-foundry' import '@nomicfoundation/hardhat-toolbox' +import '@nomicfoundation/hardhat-ignition-ethers' import 'hardhat-storage-layout' import 'hardhat-contract-sizer' @@ -19,6 +20,34 @@ const config: HardhatUserConfig = { artifacts: './build/contracts', sources: './contracts', }, + networks: { + hardhat: { + accounts: { + mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', + }, + }, + arbitrumSepolia: { + url: 'https://sepolia-rollup.arbitrum.io/rpc', + accounts: { + mnemonic: process.env.MNEMONIC ?? '', + }, + }, + }, + etherscan: { + apiKey: { + arbitrumSepolia: process.env.ETHERSCAN_API_KEY ?? '', + }, + customChains: [ + { + network: 'arbitrumSepolia', + chainId: 421614, + urls: { + apiURL: 'https://api-sepolia.arbiscan.io/api', + browserURL: 'https://sepolia.arbiscan.io/', + }, + }, + ], + }, } export default config diff --git a/packages/horizon/ignition/configs/horizon.hardhat.json b/packages/horizon/ignition/configs/horizon.hardhat.json new file mode 100644 index 000000000..894a2ed59 --- /dev/null +++ b/packages/horizon/ignition/configs/horizon.hardhat.json @@ -0,0 +1,46 @@ +{ + "GraphProxyAdmin": { + "governor": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0" + }, + "Controller": { + "governor": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", + "pauseGuardian": "0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC" + }, + "RewardsManager": { + "subgraphAvailabilityOracle": "0xd03ea8624C8C5987235048901fB614fDcA89b117", + "issuancePerBlock": "114155251141552511415n", + "subgraphServiceAddress": "0x0000000000000000000000000000000000000000" + }, + "EpochManager": { + "epochLength": 60 + }, + "GraphTokenGateway": { + "pauseGuardian": "0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC" + }, + "Curation": { + "curationTaxPercentage": 10000, + "minimumCurationDeposit": 1 + }, + "GraphToken": { + "initialSupply": "10000000000000000000000000000n", + "governor": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0" + }, + "HorizonStaking": { + "subgraphServiceAddress": "0x0000000000000000000000000000000000000000", + "maxThawingPeriod": 2419200 + }, + "HorizonStakingExtension": { + "subgraphServiceAddress": "0x0000000000000000000000000000000000000000" + }, + "GraphPayments": { + "protocolPaymentCut": 10000 + }, + "PaymentsEscrow": { + "revokeCollectorThawingPeriod": 10000, + "withdrawEscrowThawingPeriod": 10000 + }, + "TAPCollector": { + "eip712Name": "TAPCollector", + "eip712Version": "1" + } +} diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow.json new file mode 100644 index 000000000..3e87653d9 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow.json @@ -0,0 +1,159 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeEscrow", + "sourceName": "contracts/gateway/BridgeEscrow.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "approveAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "revokeAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051610c376101696000398061071f5250806106f65250806106cd528061089e5250806106a452508061067b5250806106525250806106295250610c376000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow_Instance.json new file mode 100644 index 000000000..3e87653d9 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#BridgeEscrow_Instance.json @@ -0,0 +1,159 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeEscrow", + "sourceName": "contracts/gateway/BridgeEscrow.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "approveAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "revokeAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051610c376101696000398061071f5250806106f65250806106cd528061089e5250806106a452508061067b5250806106525250806106295250610c376000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#GraphProxy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/BridgeEscrow#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/Controller#Controller.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Controller#Controller.json new file mode 100644 index 000000000..c74445ff4 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Controller#Controller.json @@ -0,0 +1,349 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Controller", + "sourceName": "contracts/governance/Controller.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PartialPauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "SetContractProxy", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + } + ], + "name": "getContractProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPausePartialTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPauseTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "partialPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_contractAddress", + "type": "address" + } + ], + "name": "setContractProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_toPause", + "type": "bool" + } + ], + "name": "setPartialPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPauseGuardian", + "type": "address" + } + ], + "name": "setPauseGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_toPause", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + } + ], + "name": "unsetContractProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "updateController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506100243361003360201b6109b21760201c565b61002e6001610055565b6100e7565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff1615158115151415610075576100e4565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff910416156100a157426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a15b50565b610ba0806100f66000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80636cda3798116100a2578063e0e9929211610071578063e0e9929214610215578063e3056a3414610241578063eb5dd94f14610249578063f2fde38b14610275578063f7641a5e1461029b5761010b565b80636cda3798146101ce57806379ba5097146101e85780639181df9c146101f057806391b4ded91461020d5761010b565b806348bde20c116100de57806348bde20c146101795780634fc07d751461019f57806356371bd8146101a75780635c975abb146101c65761010b565b80630c340a241461011057806316c38b3c1461013457806324a3d622146101555780632e292fc71461015d575b600080fd5b6101186102b8565b604080516001600160a01b039092168252519081900360200190f35b6101536004803603602081101561014a57600080fd5b503515156102c7565b005b610118610331565b610165610340565b604080519115158252519081900360200190f35b6101536004803603602081101561018f57600080fd5b50356001600160a01b0316610350565b61011861040c565b610153600480360360208110156101bd57600080fd5b5035151561041b565b610165610482565b6101d6610492565b60408051918252519081900360200190f35b610153610498565b6101536004803603602081101561020657600080fd5b50356105a6565b6101d6610651565b6101536004803603604081101561022b57600080fd5b50803590602001356001600160a01b0316610657565b61011861076e565b6101536004803603604081101561025f57600080fd5b50803590602001356001600160a01b031661077d565b6101536004803603602081101561028b57600080fd5b50356001600160a01b0316610899565b610118600480360360208110156102b157600080fd5b5035610997565b6000546001600160a01b031681565b6000546001600160a01b03163314806102ea57506004546001600160a01b031633145b6103255760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e816109d4565b50565b6004546001600160a01b031681565b600154600160a01b900460ff1690565b6000546001600160a01b031633146103a8576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610403576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b61032e81610a65565b6000546001600160a01b031690565b6000546001600160a01b031633148061043e57506004546001600160a01b031633145b6104795760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e81610ab7565b600154600160a81b900460ff1690565b60025481565b6001546001600160a01b031680158015906104bb5750336001600160a01b038216145b61050c576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b031916905580519283525183927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a250565b60035481565b6000546001600160a01b031633146106af576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661070a576040805162461bcd60e51b815260206004820152601c60248201527f436f6e74726163742061646472657373206d7573742062652073657400000000604482015290519081900360640190fd5b60008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a25050565b6001546001600160a01b031681565b6000546001600160a01b031633146107d5576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610829576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b6000828152600560205260408082205481516392eefe9b60e01b81526001600160a01b038581166004830152925192909116926392eefe9b9260248084019382900301818387803b15801561087d57600080fd5b505af1158015610891573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146108f1576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610943576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000908152600560205260409020546001600160a01b031690565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff16151581151514156109f45761032e565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615610a2057426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b600160149054906101000a900460ff1615158115151415610ad75761032e565b6001805460ff60a01b1916600160a01b8315158102919091179182905560ff91041615610b0357426002555b60015460408051600160a01b90920460ff1615158252517f511b770d1b1dc5cbd412a5017f55cbb2295b826385e5f46c1de2b6ebeb44ae02916020908290030190a15056fe4f6e6c7920476f7665726e6f72206f7220477561726469616e2063616e2063616c6ca2646970667358221220c742dbbf8f38fda928d26053c584788bb7d7b003131594b9e14f1381ebbdbb3064736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80636cda3798116100a2578063e0e9929211610071578063e0e9929214610215578063e3056a3414610241578063eb5dd94f14610249578063f2fde38b14610275578063f7641a5e1461029b5761010b565b80636cda3798146101ce57806379ba5097146101e85780639181df9c146101f057806391b4ded91461020d5761010b565b806348bde20c116100de57806348bde20c146101795780634fc07d751461019f57806356371bd8146101a75780635c975abb146101c65761010b565b80630c340a241461011057806316c38b3c1461013457806324a3d622146101555780632e292fc71461015d575b600080fd5b6101186102b8565b604080516001600160a01b039092168252519081900360200190f35b6101536004803603602081101561014a57600080fd5b503515156102c7565b005b610118610331565b610165610340565b604080519115158252519081900360200190f35b6101536004803603602081101561018f57600080fd5b50356001600160a01b0316610350565b61011861040c565b610153600480360360208110156101bd57600080fd5b5035151561041b565b610165610482565b6101d6610492565b60408051918252519081900360200190f35b610153610498565b6101536004803603602081101561020657600080fd5b50356105a6565b6101d6610651565b6101536004803603604081101561022b57600080fd5b50803590602001356001600160a01b0316610657565b61011861076e565b6101536004803603604081101561025f57600080fd5b50803590602001356001600160a01b031661077d565b6101536004803603602081101561028b57600080fd5b50356001600160a01b0316610899565b610118600480360360208110156102b157600080fd5b5035610997565b6000546001600160a01b031681565b6000546001600160a01b03163314806102ea57506004546001600160a01b031633145b6103255760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e816109d4565b50565b6004546001600160a01b031681565b600154600160a01b900460ff1690565b6000546001600160a01b031633146103a8576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610403576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b61032e81610a65565b6000546001600160a01b031690565b6000546001600160a01b031633148061043e57506004546001600160a01b031633145b6104795760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e81610ab7565b600154600160a81b900460ff1690565b60025481565b6001546001600160a01b031680158015906104bb5750336001600160a01b038216145b61050c576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b031916905580519283525183927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a250565b60035481565b6000546001600160a01b031633146106af576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661070a576040805162461bcd60e51b815260206004820152601c60248201527f436f6e74726163742061646472657373206d7573742062652073657400000000604482015290519081900360640190fd5b60008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a25050565b6001546001600160a01b031681565b6000546001600160a01b031633146107d5576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610829576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b6000828152600560205260408082205481516392eefe9b60e01b81526001600160a01b038581166004830152925192909116926392eefe9b9260248084019382900301818387803b15801561087d57600080fd5b505af1158015610891573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146108f1576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610943576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000908152600560205260409020546001600160a01b031690565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff16151581151514156109f45761032e565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615610a2057426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b600160149054906101000a900460ff1615158115151415610ad75761032e565b6001805460ff60a01b1916600160a01b8315158102919091179182905560ff91041615610b0357426002555b60015460408051600160a01b90920460ff1615158252517f511b770d1b1dc5cbd412a5017f55cbb2295b826385e5f46c1de2b6ebeb44ae02916020908290030190a15056fe4f6e6c7920476f7665726e6f72206f7220477561726469616e2063616e2063616c6ca2646970667358221220c742dbbf8f38fda928d26053c584788bb7d7b003131594b9e14f1381ebbdbb3064736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation.json new file mode 100644 index 000000000..f9d96cee6 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation.json @@ -0,0 +1,707 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2Curation", + "sourceName": "contracts/l2/curation/L2Curation.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Collected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curationTax", + "type": "uint256" + } + ], + "name": "Signalled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bondingCurve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_tokensOutMin", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTaxPercentage", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTokenMaster", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultReserveRatio", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCuratorSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_curationTaxPercentage", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isCurated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumCurationDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_signalOutMin", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "mintTaxFree", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "reserveRatio", + "type": "uint32" + }, + { + "internalType": "contract IGraphCurationToken", + "name": "gcs", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_percentage", + "type": "uint32" + } + ], + "name": "setCurationTaxPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + } + ], + "name": "setCurationTokenMaster", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "setDefaultReserveRatio", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "setMinimumCurationDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + } + ], + "name": "signalToTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalToTokensNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6101806040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea361014052613d0960e61b6101605234801561011a57600080fd5b5060805160a05160c05160e0516101005161012051610140516101605160e01c6128cc61018f60003980610c2f52508061141b52806119025250806113f25250806113c9528061180c5250806113a05280611dbf5250806113775280611ff252508061134e52508061132552506128cc6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation_Instance.json new file mode 100644 index 000000000..f9d96cee6 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#Curation_Instance.json @@ -0,0 +1,707 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2Curation", + "sourceName": "contracts/l2/curation/L2Curation.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Collected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curationTax", + "type": "uint256" + } + ], + "name": "Signalled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bondingCurve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_tokensOutMin", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTaxPercentage", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTokenMaster", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultReserveRatio", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCuratorSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_curationTaxPercentage", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isCurated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumCurationDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_signalOutMin", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "mintTaxFree", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "reserveRatio", + "type": "uint32" + }, + { + "internalType": "contract IGraphCurationToken", + "name": "gcs", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_percentage", + "type": "uint32" + } + ], + "name": "setCurationTaxPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + } + ], + "name": "setCurationTokenMaster", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "setDefaultReserveRatio", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "setMinimumCurationDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + } + ], + "name": "signalToTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalToTokensNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6101806040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea361014052613d0960e61b6101605234801561011a57600080fd5b5060805160a05160c05160e0516101005161012051610140516101605160e01c6128cc61018f60003980610c2f52508061141b52806119025250806113f25250806113c9528061180c5250806113a05280611dbf5250806113775280611ff252508061134e52508061132552506128cc6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphCurationToken.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphCurationToken.json new file mode 100644 index 000000000..b7220dcc7 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphCurationToken.json @@ -0,0 +1,414 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphCurationToken", + "sourceName": "contracts/curation/GraphCurationToken.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506114ec806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806379ba5097116100a2578063a9059cbb11610071578063a9059cbb14610352578063c4d66de81461037e578063dd62ed3e146103a4578063e3056a34146103d2578063f2fde38b146103da57610116565b806379ba5097146102ea57806379cc6790146102f257806395d89b411461031e578063a457c2d71461032657610116565b806323b872dd116100e957806323b872dd14610216578063313ce5671461024c578063395093511461026a57806340c10f191461029657806370a08231146102c457610116565b806306fdde031461011b578063095ea7b3146101985780630c340a24146101d857806318160ddd146101fc575b600080fd5b610123610400565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015d578181015183820152602001610145565b50505050905090810190601f16801561018a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c4600480360360408110156101ae57600080fd5b506001600160a01b038135169060200135610496565b604080519115158252519081900360200190f35b6101e06104b3565b604080516001600160a01b039092168252519081900360200190f35b6102046104c2565b60408051918252519081900360200190f35b6101c46004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356104c8565b61025461054f565b6040805160ff9092168252519081900360200190f35b6101c46004803603604081101561028057600080fd5b506001600160a01b038135169060200135610558565b6102c2600480360360408110156102ac57600080fd5b506001600160a01b0381351690602001356105a6565b005b610204600480360360208110156102da57600080fd5b50356001600160a01b031661060c565b6102c2610627565b6102c26004803603604081101561030857600080fd5b506001600160a01b038135169060200135610737565b610123610799565b6101c46004803603604081101561033c57600080fd5b506001600160a01b0381351690602001356107fa565b6101c46004803603604081101561036857600080fd5b506001600160a01b038135169060200135610862565b6102c26004803603602081101561039457600080fd5b50356001600160a01b0316610876565b610204600480360360408110156103ba57600080fd5b506001600160a01b0381358116916020013516610972565b6101e061099d565b6102c2600480360360208110156103f057600080fd5b50356001600160a01b03166109ac565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b820191906000526020600020905b81548152906001019060200180831161046f57829003601f168201915b5050505050905090565b60006104aa6104a3610aaa565b8484610aae565b50600192915050565b6065546001600160a01b031681565b60355490565b60006104d5848484610b9a565b610545846104e1610aaa565b61054085604051806060016040528060288152602001611400602891396001600160a01b038a1660009081526034602052604081209061051f610aaa565b6001600160a01b031681526020810191909152604001600020549190610cf7565b610aae565b5060019392505050565b60385460ff1690565b60006104aa610565610aaa565b846105408560346000610576610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610d8e565b6065546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610def565b5050565b6001600160a01b031660009081526033602052604090205490565b6066546001600160a01b0316801580159061064a5750336001600160a01b038216145b61069b576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b606580546001600160a01b038381166001600160a01b0319808416919091179384905560668054909116905560405191811692169082907f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f90600090a36066546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6065546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610ee1565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b60006104aa610807610aaa565b84610540856040518060600160405280602581526020016114926025913960346000610831610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610cf7565b60006104aa61086f610aaa565b8484610b9a565b600054610100900460ff168061088f575061088f610fdd565b8061089d575060005460ff16155b6108d85760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015610903576000805460ff1961ff0019909116610100171660011790555b61090c82610fee565b61095d604051806040016040528060148152602001734772617068204375726174696f6e20536861726560601b8152506040518060400160405280600381526020016247435360e81b815250611010565b8015610608576000805461ff00191690555050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6066546001600160a01b031681565b6065546001600160a01b03163314610a04576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610a56576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b606680546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b038316610af35760405162461bcd60e51b815260040180806020018281038252602481526020018061146e6024913960400191505060405180910390fd5b6001600160a01b038216610b385760405162461bcd60e51b815260040180806020018281038252602281526020018061138a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610bdf5760405162461bcd60e51b81526004018080602001828103825260258152602001806114496025913960400191505060405180910390fd5b6001600160a01b038216610c245760405162461bcd60e51b81526004018080602001828103825260238152602001806113456023913960400191505060405180910390fd5b610c2f8383836110c1565b610c6c816040518060600160405280602681526020016113ac602691396001600160a01b0386166000908152603360205260409020549190610cf7565b6001600160a01b038085166000908152603360205260408082209390935590841681522054610c9b9082610d8e565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610d865760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d4b578181015183820152602001610d33565b50505050905090810190601f168015610d785780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610de8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610e4a576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610e56600083836110c1565b603554610e639082610d8e565b6035556001600160a01b038216600090815260336020526040902054610e899082610d8e565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610f265760405162461bcd60e51b81526004018080602001828103825260218152602001806114286021913960400191505060405180910390fd5b610f32826000836110c1565b610f6f81604051806060016040528060228152602001611368602291396001600160a01b0385166000908152603360205260409020549190610cf7565b6001600160a01b038316600090815260336020526040902055603554610f9590826110c6565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000610fe830611123565b15905090565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16806110295750611029610fdd565b80611037575060005460ff16155b6110725760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff1615801561109d576000805460ff1961ff0019909116610100171660011790555b6110a5611129565b6110af83836111cb565b80156110c1576000805461ff00191690555b505050565b60008282111561111d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600054610100900460ff16806111425750611142610fdd565b80611150575060005460ff16155b61118b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff161580156111b6576000805460ff1961ff0019909116610100171660011790555b80156111c8576000805461ff00191690555b50565b600054610100900460ff16806111e457506111e4610fdd565b806111f2575060005460ff16155b61122d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015611258576000805460ff1961ff0019909116610100171660011790555b825161126b9060369060208601906112a3565b50815161127f9060379060208501906112a3565b506038805460ff1916601217905580156110c1576000805461ff0019169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826112d9576000855561131f565b82601f106112f257805160ff191683800117855561131f565b8280016001018555821561131f579182015b8281111561131f578251825591602001919060010190611304565b5061132b92915061132f565b5090565b5b8082111561132b576000815560010161133056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200b687fddcd01dbad6e1d5fbd49cb041f69ed61684a12a4c26c6e37e0f5ad7c2a64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101165760003560e01c806379ba5097116100a2578063a9059cbb11610071578063a9059cbb14610352578063c4d66de81461037e578063dd62ed3e146103a4578063e3056a34146103d2578063f2fde38b146103da57610116565b806379ba5097146102ea57806379cc6790146102f257806395d89b411461031e578063a457c2d71461032657610116565b806323b872dd116100e957806323b872dd14610216578063313ce5671461024c578063395093511461026a57806340c10f191461029657806370a08231146102c457610116565b806306fdde031461011b578063095ea7b3146101985780630c340a24146101d857806318160ddd146101fc575b600080fd5b610123610400565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015d578181015183820152602001610145565b50505050905090810190601f16801561018a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c4600480360360408110156101ae57600080fd5b506001600160a01b038135169060200135610496565b604080519115158252519081900360200190f35b6101e06104b3565b604080516001600160a01b039092168252519081900360200190f35b6102046104c2565b60408051918252519081900360200190f35b6101c46004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356104c8565b61025461054f565b6040805160ff9092168252519081900360200190f35b6101c46004803603604081101561028057600080fd5b506001600160a01b038135169060200135610558565b6102c2600480360360408110156102ac57600080fd5b506001600160a01b0381351690602001356105a6565b005b610204600480360360208110156102da57600080fd5b50356001600160a01b031661060c565b6102c2610627565b6102c26004803603604081101561030857600080fd5b506001600160a01b038135169060200135610737565b610123610799565b6101c46004803603604081101561033c57600080fd5b506001600160a01b0381351690602001356107fa565b6101c46004803603604081101561036857600080fd5b506001600160a01b038135169060200135610862565b6102c26004803603602081101561039457600080fd5b50356001600160a01b0316610876565b610204600480360360408110156103ba57600080fd5b506001600160a01b0381358116916020013516610972565b6101e061099d565b6102c2600480360360208110156103f057600080fd5b50356001600160a01b03166109ac565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b820191906000526020600020905b81548152906001019060200180831161046f57829003601f168201915b5050505050905090565b60006104aa6104a3610aaa565b8484610aae565b50600192915050565b6065546001600160a01b031681565b60355490565b60006104d5848484610b9a565b610545846104e1610aaa565b61054085604051806060016040528060288152602001611400602891396001600160a01b038a1660009081526034602052604081209061051f610aaa565b6001600160a01b031681526020810191909152604001600020549190610cf7565b610aae565b5060019392505050565b60385460ff1690565b60006104aa610565610aaa565b846105408560346000610576610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610d8e565b6065546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610def565b5050565b6001600160a01b031660009081526033602052604090205490565b6066546001600160a01b0316801580159061064a5750336001600160a01b038216145b61069b576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b606580546001600160a01b038381166001600160a01b0319808416919091179384905560668054909116905560405191811692169082907f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f90600090a36066546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6065546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610ee1565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b60006104aa610807610aaa565b84610540856040518060600160405280602581526020016114926025913960346000610831610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610cf7565b60006104aa61086f610aaa565b8484610b9a565b600054610100900460ff168061088f575061088f610fdd565b8061089d575060005460ff16155b6108d85760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015610903576000805460ff1961ff0019909116610100171660011790555b61090c82610fee565b61095d604051806040016040528060148152602001734772617068204375726174696f6e20536861726560601b8152506040518060400160405280600381526020016247435360e81b815250611010565b8015610608576000805461ff00191690555050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6066546001600160a01b031681565b6065546001600160a01b03163314610a04576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610a56576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b606680546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b038316610af35760405162461bcd60e51b815260040180806020018281038252602481526020018061146e6024913960400191505060405180910390fd5b6001600160a01b038216610b385760405162461bcd60e51b815260040180806020018281038252602281526020018061138a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610bdf5760405162461bcd60e51b81526004018080602001828103825260258152602001806114496025913960400191505060405180910390fd5b6001600160a01b038216610c245760405162461bcd60e51b81526004018080602001828103825260238152602001806113456023913960400191505060405180910390fd5b610c2f8383836110c1565b610c6c816040518060600160405280602681526020016113ac602691396001600160a01b0386166000908152603360205260409020549190610cf7565b6001600160a01b038085166000908152603360205260408082209390935590841681522054610c9b9082610d8e565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610d865760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d4b578181015183820152602001610d33565b50505050905090810190601f168015610d785780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610de8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610e4a576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610e56600083836110c1565b603554610e639082610d8e565b6035556001600160a01b038216600090815260336020526040902054610e899082610d8e565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610f265760405162461bcd60e51b81526004018080602001828103825260218152602001806114286021913960400191505060405180910390fd5b610f32826000836110c1565b610f6f81604051806060016040528060228152602001611368602291396001600160a01b0385166000908152603360205260409020549190610cf7565b6001600160a01b038316600090815260336020526040902055603554610f9590826110c6565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000610fe830611123565b15905090565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16806110295750611029610fdd565b80611037575060005460ff16155b6110725760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff1615801561109d576000805460ff1961ff0019909116610100171660011790555b6110a5611129565b6110af83836111cb565b80156110c1576000805461ff00191690555b505050565b60008282111561111d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600054610100900460ff16806111425750611142610fdd565b80611150575060005460ff16155b61118b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff161580156111b6576000805460ff1961ff0019909116610100171660011790555b80156111c8576000805461ff00191690555b50565b600054610100900460ff16806111e457506111e4610fdd565b806111f2575060005460ff16155b61122d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015611258576000805460ff1961ff0019909116610100171660011790555b825161126b9060369060208601906112a3565b50815161127f9060379060208501906112a3565b506038805460ff1916601217905580156110c1576000805461ff0019169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826112d9576000855561131f565b82601f106112f257805160ff191683800117855561131f565b8280016001018555821561131f579182015b8281111561131f578251825591602001919060010190611304565b5061132b92915061132f565b5090565b5b8082111561132b576000815560010161133056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200b687fddcd01dbad6e1d5fbd49cb041f69ed61684a12a4c26c6e37e0f5ad7c2a64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphProxy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/Curation#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager.json new file mode 100644 index 000000000..cd09f36f8 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager.json @@ -0,0 +1,364 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EpochManager", + "sourceName": "contracts/epochs/EpochManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochLength", + "type": "uint256" + } + ], + "name": "EpochLengthUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "EpochRun", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlockSinceStart", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "epochsSince", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochsSinceUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isCurrentEpochRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRunEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "runEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "setEpochLength", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161103461016460003980610aac525080610a83525080610a5a525080610a31525080610a085250806109df5250806109b652506110346000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager_Instance.json new file mode 100644 index 000000000..cd09f36f8 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#EpochManager_Instance.json @@ -0,0 +1,364 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EpochManager", + "sourceName": "contracts/epochs/EpochManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochLength", + "type": "uint256" + } + ], + "name": "EpochLengthUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "EpochRun", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlockSinceStart", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "epochsSince", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochsSinceUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isCurrentEpochRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRunEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "runEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "setEpochLength", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161103461016460003980610aac525080610a83525080610a5a525080610a31525080610a085250806109df5250806109b652506110346000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#GraphProxy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/EpochManager#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphHorizon_Periphery#Dummy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphHorizon_Periphery#Dummy.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphHorizon_Periphery#Dummy.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments.json new file mode 100644 index 000000000..d9b94acde --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments.json @@ -0,0 +1,308 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphPayments", + "sourceName": "contracts/payments/GraphPayments.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "GraphPaymentsInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "name": "GraphPaymentsInvalidProtocolPaymentCut", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensReceiver", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDelegationPool", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensProtocol", + "type": "uint256" + } + ], + "name": "PaymentCollected", + "type": "event" + }, + { + "inputs": [], + "name": "PROTOCOL_PAYMENT_CUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101e060405234801561001157600080fd5b5060405161132f38038061132f833981016040819052610030916104ee565b816001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b290610372565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e590610372565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e90610372565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015890610372565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019090610372565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb90610372565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020990610372565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024590610372565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a90610372565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a45061033a81620f4240101590565b819061035c5760405163d3097bcb60e01b815260040161007191815260200190565b506101c081905261036b610420565b505061058a565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103ad91815260200190565b602060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ee919061051a565b9050826001600160a01b0382166104195760405163218f5add60e11b8152600401610071919061053c565b5092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156104705760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146104cf5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146104e957600080fd5b919050565b6000806040838503121561050157600080fd5b61050a836104d2565b9150602083015190509250929050565b60006020828403121561052c57600080fd5b610535826104d2565b9392505050565b602081526000825180602084015260005b8181101561056a576020818601810151604086840101520161054d565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051610d086106276000396000818160560152610104015260005050600050506000505060005050600050506000505060005050600050506000818161012e015281816102c1015261035401526000818160d5015281816102220152818161025a0152818161029201526103f50152610d086000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments_Instance.json new file mode 100644 index 000000000..d9b94acde --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphPayments#GraphPayments_Instance.json @@ -0,0 +1,308 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphPayments", + "sourceName": "contracts/payments/GraphPayments.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "GraphPaymentsInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "name": "GraphPaymentsInvalidProtocolPaymentCut", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensReceiver", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDelegationPool", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensProtocol", + "type": "uint256" + } + ], + "name": "PaymentCollected", + "type": "event" + }, + { + "inputs": [], + "name": "PROTOCOL_PAYMENT_CUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101e060405234801561001157600080fd5b5060405161132f38038061132f833981016040819052610030916104ee565b816001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b290610372565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e590610372565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e90610372565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015890610372565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019090610372565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb90610372565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020990610372565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024590610372565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a90610372565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a45061033a81620f4240101590565b819061035c5760405163d3097bcb60e01b815260040161007191815260200190565b506101c081905261036b610420565b505061058a565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103ad91815260200190565b602060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ee919061051a565b9050826001600160a01b0382166104195760405163218f5add60e11b8152600401610071919061053c565b5092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156104705760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146104cf5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146104e957600080fd5b919050565b6000806040838503121561050157600080fd5b61050a836104d2565b9150602083015190509250929050565b60006020828403121561052c57600080fd5b610535826104d2565b9392505050565b602081526000825180602084015260005b8181101561056a576020818601810151604086840101520161054d565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051610d086106276000396000818160560152610104015260005050600050506000505060005050600050506000505060005050600050506000818161012e015281816102c1015261035401526000818160d5015281816102220152818161025a0152818161029201526103f50152610d086000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphProxyAdmin#GraphProxyAdmin.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphProxyAdmin#GraphProxyAdmin.json new file mode 100644 index 000000000..07f0623c5 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphProxyAdmin#GraphProxyAdmin.json @@ -0,0 +1,234 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxyAdmin", + "sourceName": "contracts/upgrades/GraphProxyAdmin.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract GraphUpgradeable", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract GraphUpgradeable", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "getProxyPendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506100243361002960201b610a0c1760201c565b61004b565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610a648061005a6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80637eff275e116100715780637eff275e146101b157806399a88ec4146101df578063e3056a341461020d578063eb451a0214610215578063f2fde38b14610243578063f3b7dead14610269576100a9565b806307ebde0e146100ae5780630c340a2414610139578063204e1c7a1461015d5780635bf410eb1461018357806379ba5097146101a9575b600080fd5b610137600480360360608110156100c457600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b50909250905061028f565b005b610141610388565b604080516001600160a01b039092168252519081900360200190f35b6101416004803603602081101561017357600080fd5b50356001600160a01b0316610397565b6101416004803603602081101561019957600080fd5b50356001600160a01b031661046a565b610137610525565b610137600480360360408110156101c757600080fd5b506001600160a01b0381358116916020013516610633565b610137600480360360408110156101f557600080fd5b506001600160a01b03813581169160200135166106f6565b61014161079d565b6101376004803603604081101561022b57600080fd5b506001600160a01b03813581169160200135166107ac565b6101376004803603602081101561025957600080fd5b50356001600160a01b0316610853565b6101416004803603602081101561027f57600080fd5b50356001600160a01b0316610951565b6000546001600160a01b031633146102e7576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b836001600160a01b0316639ce7abe58484846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b15801561036a57600080fd5b505af115801561037e573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031681565b6000806000836001600160a01b03166040518080635c60da1b60e01b8152506004019050600060405180830381855afa9150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b50915091508161044b576040805162461bcd60e51b8152602060048201526016602482015275141c9bde1e481a5b5c1b0818d85b1b0819985a5b195960521b604482015290519081900360640190fd5b80806020019051602081101561046057600080fd5b5051949350505050565b6000806000836001600160a01b0316604051808063396f7b2360e01b8152506004019050600060405180830381855afa9150503d80600081146104c9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ce565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601d60248201527f50726f78792070656e64696e67496d706c2063616c6c206661696c6564000000604482015290519081900360640190fd5b6001546001600160a01b031680158015906105485750336001600160a01b038216145b610599576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b0316331461068b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663704b6c02826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b505af11580156106ee573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461074e576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b0316633659cfe6826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6001546001600160a01b031681565b6000546001600160a01b03163314610804576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663a2594d82826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6000546001600160a01b031633146108ab576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b0381166108fd576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000806000836001600160a01b031660405180806303e1469160e61b8152506004019050600060405180830381855afa9150503d80600081146109b0576040519150601f19603f3d011682016040523d82523d6000602084013e6109b5565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601760248201527f50726f78792061646d696e2063616c6c206661696c6564000000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b039290921691909117905556fea26469706673582212208b271ee4c7625d89f662c15e90f70e142245bf56f0595043fe9af742b09d958c64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80637eff275e116100715780637eff275e146101b157806399a88ec4146101df578063e3056a341461020d578063eb451a0214610215578063f2fde38b14610243578063f3b7dead14610269576100a9565b806307ebde0e146100ae5780630c340a2414610139578063204e1c7a1461015d5780635bf410eb1461018357806379ba5097146101a9575b600080fd5b610137600480360360608110156100c457600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b50909250905061028f565b005b610141610388565b604080516001600160a01b039092168252519081900360200190f35b6101416004803603602081101561017357600080fd5b50356001600160a01b0316610397565b6101416004803603602081101561019957600080fd5b50356001600160a01b031661046a565b610137610525565b610137600480360360408110156101c757600080fd5b506001600160a01b0381358116916020013516610633565b610137600480360360408110156101f557600080fd5b506001600160a01b03813581169160200135166106f6565b61014161079d565b6101376004803603604081101561022b57600080fd5b506001600160a01b03813581169160200135166107ac565b6101376004803603602081101561025957600080fd5b50356001600160a01b0316610853565b6101416004803603602081101561027f57600080fd5b50356001600160a01b0316610951565b6000546001600160a01b031633146102e7576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b836001600160a01b0316639ce7abe58484846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b15801561036a57600080fd5b505af115801561037e573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031681565b6000806000836001600160a01b03166040518080635c60da1b60e01b8152506004019050600060405180830381855afa9150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b50915091508161044b576040805162461bcd60e51b8152602060048201526016602482015275141c9bde1e481a5b5c1b0818d85b1b0819985a5b195960521b604482015290519081900360640190fd5b80806020019051602081101561046057600080fd5b5051949350505050565b6000806000836001600160a01b0316604051808063396f7b2360e01b8152506004019050600060405180830381855afa9150503d80600081146104c9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ce565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601d60248201527f50726f78792070656e64696e67496d706c2063616c6c206661696c6564000000604482015290519081900360640190fd5b6001546001600160a01b031680158015906105485750336001600160a01b038216145b610599576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b0316331461068b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663704b6c02826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b505af11580156106ee573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461074e576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b0316633659cfe6826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6001546001600160a01b031681565b6000546001600160a01b03163314610804576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663a2594d82826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6000546001600160a01b031633146108ab576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b0381166108fd576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000806000836001600160a01b031660405180806303e1469160e61b8152506004019050600060405180830381855afa9150503d80600081146109b0576040519150601f19603f3d011682016040523d82523d6000602084013e6109b5565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601760248201527f50726f78792061646d696e2063616c6c206661696c6564000000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b039290921691909117905556fea26469706673582212208b271ee4c7625d89f662c15e90f70e142245bf56f0595043fe9af742b09d958c64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphProxy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken.json new file mode 100644 index 000000000..5889eeaf0 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken.json @@ -0,0 +1,750 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphToken", + "sourceName": "contracts/l2/token/L2GraphToken.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "name": "GatewaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "L1AddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Address", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "removeMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gw", + "type": "address" + } + ], + "name": "setGateway", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "setL1Address", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101206040527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726080527fefcec85968da792893fa503eb21730083fc6c50ed5461e56163b28335b2a5f9660a0527f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d60c0527fe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f565959160e0527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610100523480156100c657600080fd5b5060805160a05160c05160e0516101005161261e61010660003980611547525080611eae525080611e5e525080611e3d525080611e1c525061261e6000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken_Instance.json new file mode 100644 index 000000000..5889eeaf0 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphToken#GraphToken_Instance.json @@ -0,0 +1,750 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphToken", + "sourceName": "contracts/l2/token/L2GraphToken.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "name": "GatewaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "L1AddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Address", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "removeMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gw", + "type": "address" + } + ], + "name": "setGateway", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "setL1Address", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101206040527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726080527fefcec85968da792893fa503eb21730083fc6c50ed5461e56163b28335b2a5f9660a0527f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d60c0527fe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f565959160e0527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610100523480156100c657600080fd5b5060805160a05160c05160e0516101005161261e61010660003980611547525080611eae525080611e5e525080611e3d525080611e1c525061261e6000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphProxy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway.json new file mode 100644 index 000000000..a9c54a794 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway.json @@ -0,0 +1,647 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphTokenGateway", + "sourceName": "contracts/l2/gateway/L2GraphTokenGateway.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Counterpart", + "type": "address" + } + ], + "name": "L1CounterpartAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1GRT", + "type": "address" + } + ], + "name": "L1TokenAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l2Router", + "type": "address" + } + ], + "name": "L2RouterSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PartialPauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "TxToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "l2ToL1Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawalInitiated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Counterpart", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1GRT", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Router", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPausePartialTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPauseTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Counterpart", + "type": "address" + } + ], + "name": "setL1CounterpartAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1GRT", + "type": "address" + } + ], + "name": "setL1TokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Router", + "type": "address" + } + ], + "name": "setL2Router", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPauseGuardian", + "type": "address" + } + ], + "name": "setPauseGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_newPaused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161222b6101696000398061112f5250806111065250806110dd528061150a5250806110b452508061108b525080611062525080611039525061222b6000f3fe6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "deployedBytecode": "0x6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json new file mode 100644 index 000000000..a9c54a794 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json @@ -0,0 +1,647 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphTokenGateway", + "sourceName": "contracts/l2/gateway/L2GraphTokenGateway.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Counterpart", + "type": "address" + } + ], + "name": "L1CounterpartAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1GRT", + "type": "address" + } + ], + "name": "L1TokenAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l2Router", + "type": "address" + } + ], + "name": "L2RouterSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PartialPauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "TxToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "l2ToL1Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawalInitiated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Counterpart", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1GRT", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Router", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPausePartialTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPauseTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Counterpart", + "type": "address" + } + ], + "name": "setL1CounterpartAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1GRT", + "type": "address" + } + ], + "name": "setL1TokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Router", + "type": "address" + } + ], + "name": "setL2Router", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPauseGuardian", + "type": "address" + } + ], + "name": "setPauseGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_newPaused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161222b6101696000398061112f5250806111065250806110dd528061150a5250806110b452508061108b525080611062525080611039525061222b6000f3fe6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "deployedBytecode": "0x6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json new file mode 100644 index 000000000..942e4b2e5 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json @@ -0,0 +1,132 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ProxyAdmin", + "sourceName": "contracts/proxy/transparent/ProxyAdmin.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "deployedBytecode": "0x60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json new file mode 100644 index 000000000..942e4b2e5 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json @@ -0,0 +1,132 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ProxyAdmin", + "sourceName": "contracts/proxy/transparent/ProxyAdmin.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "deployedBytecode": "0x60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#RegisteredDummy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#RegisteredDummy.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#RegisteredDummy.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json new file mode 100644 index 000000000..c7f1f49b4 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TransparentUpgradeableProxy", + "sourceName": "contracts/proxy/transparent/TransparentUpgradeableProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "ERC1967InvalidAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "ProxyDeniedAdminAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json new file mode 100644 index 000000000..c7f1f49b4 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TransparentUpgradeableProxy", + "sourceName": "contracts/proxy/transparent/TransparentUpgradeableProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "ERC1967InvalidAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "ProxyDeniedAdminAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking.json new file mode 100644 index 000000000..e442f237e --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking.json @@ -0,0 +1,2280 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HorizonStaking", + "sourceName": "contracts/staking/HorizonStaking.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "address", + "name": "stakingExtensionAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "subgraphDataServiceAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingCallerIsServiceProvider", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientIdleStake", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientShares", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientStakeForLegacyAllocations", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minRequired", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "HorizonStakingInvalidDelegationFeeCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidDelegationPoolState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxMaxVerifierCut", + "type": "uint32" + } + ], + "name": "HorizonStakingInvalidMaxVerifierCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidProvision", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "HorizonStakingInvalidThawingPeriod", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroShares", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingNotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingNothingThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingProvisionAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingSlippageProtection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "HorizonStakingStillThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingTooManyThawRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingTooManyTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingVerifierNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListEmptyList", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidIterations", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidZeroId", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListMaxElementsExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyController", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyGovernor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AllowedLockedVerifierSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegatedTokensWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "DelegationFeeCutSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "DelegationSlashingEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashingSkipped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "MaxThawingPeriodSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersStaged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionThawed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "ThawRequestCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + } + ], + "name": "ThawRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawRequestsFulfilled", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ThawRequestsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ThawingPeriodCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDeprovisioned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensToDelegationPoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensUndelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "VerifierTokensSent", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "acceptProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToDelegationPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSharesOut", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "deprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegatedTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.Delegation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + } + ], + "name": "getDelegationFeeCut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegationPool", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.DelegationPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getIdleStake", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProviderTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProvision", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "createdAt", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxVerifierCutPending", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriodPending", + "type": "uint64" + } + ], + "internalType": "struct IHorizonStakingTypes.Provision", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getServiceProvider", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokensStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensProvisioned", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.ServiceProvider", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "getThawRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "next", + "type": "bytes32" + } + ], + "internalType": "struct IHorizonStakingTypes.ThawRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawRequestList", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "head", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tail", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "internalType": "struct LinkedList.List", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delegationRatio", + "type": "uint32" + } + ], + "name": "getTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAllowedLockedVerifier", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAuthorized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDelegationSlashingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provisionLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "oldVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newVerifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "reprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAllowedLockedVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "setDelegationFeeCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setDelegationSlashingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "setMaxThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperatorLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "setProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensVerifier", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifierDestination", + "type": "address" + } + ], + "name": "slash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minSharesForNewProvider", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b50604051615b2c380380615b2c8339810160408190526100309161041b565b828181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610351565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610351565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610351565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610351565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610351565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610351565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610351565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610351565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610351565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b039081166101c052929092166101e052506104ce915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038c91815260200190565b602060405180830381865afa1580156103a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cd919061045e565b9050826001600160a01b0382166103f85760405163218f5add60e11b81526004016100749190610480565b5092915050565b80516001600160a01b038116811461041657600080fd5b919050565b60008060006060848603121561043057600080fd5b610439846103ff565b9250610447602085016103ff565b9150610455604085016103ff565b90509250925092565b60006020828403121561047057600080fd5b610479826103ff565b9392505050565b602081526000825180602084015260005b818110156104ae5760208186018101516040868401015201610491565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516155836105a960003960006102fb015260008181610dbf015281816115b60152818161166801528181612f5401528181613e120152614172015260005050600050506000505060005050600050506000612f0d015260005050600050506000505060008181610d89015281816117cd015281816125b2015281816128c80152818161295f01528181612ac00152818161380b015281816139cb01528181613d88015261401e01526155836000f3fe6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking_Instance.json new file mode 100644 index 000000000..e442f237e --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStaking#HorizonStaking_Instance.json @@ -0,0 +1,2280 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HorizonStaking", + "sourceName": "contracts/staking/HorizonStaking.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "address", + "name": "stakingExtensionAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "subgraphDataServiceAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingCallerIsServiceProvider", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientIdleStake", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientShares", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientStakeForLegacyAllocations", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minRequired", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "HorizonStakingInvalidDelegationFeeCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidDelegationPoolState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxMaxVerifierCut", + "type": "uint32" + } + ], + "name": "HorizonStakingInvalidMaxVerifierCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidProvision", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "HorizonStakingInvalidThawingPeriod", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroShares", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingNotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingNothingThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingProvisionAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingSlippageProtection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "HorizonStakingStillThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingTooManyThawRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingTooManyTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingVerifierNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListEmptyList", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidIterations", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidZeroId", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListMaxElementsExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyController", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyGovernor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AllowedLockedVerifierSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegatedTokensWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "DelegationFeeCutSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "DelegationSlashingEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashingSkipped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "MaxThawingPeriodSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersStaged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionThawed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "ThawRequestCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + } + ], + "name": "ThawRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawRequestsFulfilled", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ThawRequestsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ThawingPeriodCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDeprovisioned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensToDelegationPoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensUndelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "VerifierTokensSent", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "acceptProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToDelegationPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSharesOut", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "deprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegatedTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.Delegation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + } + ], + "name": "getDelegationFeeCut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegationPool", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.DelegationPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getIdleStake", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProviderTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProvision", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "createdAt", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxVerifierCutPending", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriodPending", + "type": "uint64" + } + ], + "internalType": "struct IHorizonStakingTypes.Provision", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getServiceProvider", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokensStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensProvisioned", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.ServiceProvider", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "getThawRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "next", + "type": "bytes32" + } + ], + "internalType": "struct IHorizonStakingTypes.ThawRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawRequestList", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "head", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tail", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "internalType": "struct LinkedList.List", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delegationRatio", + "type": "uint32" + } + ], + "name": "getTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAllowedLockedVerifier", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAuthorized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDelegationSlashingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provisionLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "oldVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newVerifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "reprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAllowedLockedVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "setDelegationFeeCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setDelegationSlashingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "setMaxThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperatorLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "setProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensVerifier", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifierDestination", + "type": "address" + } + ], + "name": "slash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minSharesForNewProvider", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b50604051615b2c380380615b2c8339810160408190526100309161041b565b828181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610351565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610351565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610351565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610351565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610351565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610351565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610351565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610351565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610351565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b039081166101c052929092166101e052506104ce915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038c91815260200190565b602060405180830381865afa1580156103a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cd919061045e565b9050826001600160a01b0382166103f85760405163218f5add60e11b81526004016100749190610480565b5092915050565b80516001600160a01b038116811461041657600080fd5b919050565b60008060006060848603121561043057600080fd5b610439846103ff565b9250610447602085016103ff565b9150610455604085016103ff565b90509250925092565b60006020828403121561047057600080fd5b610479826103ff565b9392505050565b602081526000825180602084015260005b818110156104ae5760208186018101516040868401015201610491565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516155836105a960003960006102fb015260008181610dbf015281816115b60152818161166801528181612f5401528181613e120152614172015260005050600050506000505060005050600050506000612f0d015260005050600050506000505060008181610d89015281816117cd015281816125b2015281816128c80152818161295f01528181612ac00152818161380b015281816139cb01528181613d88015261401e01526155836000f3fe6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#ExponentialRebates.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#ExponentialRebates.json new file mode 100644 index 000000000..fc0c0c29f --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#ExponentialRebates.json @@ -0,0 +1,55 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ExponentialRebates", + "sourceName": "contracts/staking/libraries/ExponentialRebates.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "fees", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "alphaNumerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "alphaDenominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lambdaNumerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lambdaDenominator", + "type": "uint32" + } + ], + "name": "exponentialRebates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x610c2d610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c806349484d811461003a575b600080fd5b61004d610048366004610a66565b61005f565b60405190815260200160405180910390f35b6000806100728660030b8660030b61011c565b9050806000036100855787915050610112565b87600003610097576000915050610112565b60006100a98560030b8560030b61011c565b905060006100b8828a8c61013c565b9050600f6100c582610153565b13156100d657899350505050610112565b60006100ff6001607f1b6100fa866100f56100f087610ae2565b610169565b610882565b61089d565b905061010b818c6108d4565b9450505050505b9695505050505050565b600061013561012f846001607f1b610920565b83610988565b9392505050565b600061014b61012f8585610920565b949350505050565b60006101636001607f1b83610b14565b92915050565b60006101796101ff607c1b610ae2565b82121561018857506000919050565b8160000361019b57506001607f1b919050565b60008213156101c55760405162461bcd60e51b81526004016101bc90610b42565b60405180910390fd5b6000806101d66001607c1b85610b69565b91508190506001607f1b6101ea8280610b7d565b6101f49190610b14565b9050610208816710e1b3be415a0000610b7d565b6102129084610bad565b92506001607f1b6102238383610b7d565b61022d9190610b14565b9050610241816705a0913f6b1e0000610b7d565b61024b9084610bad565b92506001607f1b61025c8383610b7d565b6102669190610b14565b905061027a81670168244fdac78000610b7d565b6102849084610bad565b92506001607f1b6102958383610b7d565b61029f9190610b14565b90506102b281664807432bc18000610b7d565b6102bc9084610bad565b92506001607f1b6102cd8383610b7d565b6102d79190610b14565b90506102ea81660c0135dca04000610b7d565b6102f49084610bad565b92506001607f1b6103058383610b7d565b61030f9190610b14565b9050610322816601b707b1cdc000610b7d565b61032c9084610bad565b92506001607f1b61033d8383610b7d565b6103479190610b14565b9050610359816536e0f639b800610b7d565b6103639084610bad565b92506001607f1b6103748383610b7d565b61037e9190610b14565b905061039081650618fee9f800610b7d565b61039a9084610bad565b92506001607f1b6103ab8383610b7d565b6103b59190610b14565b90506103c681649c197dcc00610b7d565b6103d09084610bad565b92506001607f1b6103e18383610b7d565b6103eb9190610b14565b90506103fc81640e30dce400610b7d565b6104069084610bad565b92506001607f1b6104178383610b7d565b6104219190610b14565b90506104328164012ebd1300610b7d565b61043c9084610bad565b92506001607f1b61044d8383610b7d565b6104579190610b14565b9050610467816317499f00610b7d565b6104719084610bad565b92506001607f1b6104828383610b7d565b61048c9190610b14565b905061049c816301a9d480610b7d565b6104a69084610bad565b92506001607f1b6104b78383610b7d565b6104c19190610b14565b90506104d081621c6380610b7d565b6104da9084610bad565b92506001607f1b6104eb8383610b7d565b6104f59190610b14565b9050610504816201c638610b7d565b61050e9084610bad565b92506001607f1b61051f8383610b7d565b6105299190610b14565b905061053781611ab8610b7d565b6105419084610bad565b92506001607f1b6105528383610b7d565b61055c9190610b14565b905061056a8161017c610b7d565b6105749084610bad565b92506001607f1b6105858383610b7d565b61058f9190610b14565b905061059c816014610b7d565b6105a69084610bad565b92506001607f1b6105b78383610b7d565b6105c19190610b14565b90506105ce816001610b7d565b6105d89084610bad565b92506001607f1b826105f26721c3677c82b4000086610b14565b6105fc9190610bad565b6106069190610bad565b925061061184610ae2565b9350600160841b841615610657577243cbaf42a000812488fc5c220ad7b97bf6e99e61064a6cf1aaddd7742e56d32fb9f9974485610b7d565b6106549190610b14565b92505b600160831b84161561069c577105d27a9f51c31b7c2f8038212a057477999161068f6e0afe10820813d65dfe6a33c07f738f85610b7d565b6106999190610b14565b92505b600160821b8416156106e157701b4c902e273a58678d6d3bfdb93db96d026106d46f02582ab704279e8efd15e0265855c47a85610b7d565b6106de9190610b14565b92505b600160811b841615610726577003b1cc971a9bb5b9867477440d6d1577506107196f1152aaa3bf81cb9fdb76eae12d02957185610b7d565b6107239190610b14565b92505b600160801b84161561076b5770015bf0a8b1457695355fb8ac404e7a79e361075e6f2f16ac6c59de6f8d5d6f63c1482a7c8685610b7d565b6107689190610b14565b92505b6001607f1b8416156107af576fd3094c70f034de4b96ff7d5b6f99fcd86107a26f4da2cbf1be5827f9eb3ad1aa9866ebb385610b7d565b6107ac9190610b14565b92505b6001607e1b8416156107f3576fa45af1e1f40c333b3de1db4dd55f29a76107e66f63afbe7ab2082ba1a0ae5e4eb1b479dc85610b7d565b6107f09190610b14565b92505b6001607d1b841615610837576f910b022db7ae67ce76b441c27035c6a161082a6f70f5a893b608861e1f58934f97aea57d85610b7d565b6108349190610b14565b92505b6001607c1b84161561087b576f88415abbe9a76bead8d00cf112e4d4a861086e6f783eafef1c0a8f3978c7f81824d62ebf85610b7d565b6108789190610b14565b92505b5050919050565b60006001607f1b6108938484610920565b6101359190610b14565b6000600160ff1b82036108c25760405162461bcd60e51b81526004016101bc90610b42565b610135836108cf84610ae2565b6109f2565b6000808212156108f65760405162461bcd60e51b81526004016101bc90610b42565b60006109028484610920565b905060008113610916576000915050610163565b607f1c9392505050565b600082158061092d575081155b1561093a57506000610163565b508181028183828161094e5761094e610afe565b0514158061096b57508282828161096757610967610afe565b0514155b156101635760405162461bcd60e51b81526004016101bc90610bd5565b6000816000036109aa5760405162461bcd60e51b81526004016101bc90610bd5565b600160ff1b831480156109be575081600019145b156109db5760405162461bcd60e51b81526004016101bc90610bd5565b8183816109ea576109ea610afe565b059392505050565b818101600083128015610a055750600082125b8015610a1057508281135b8061096b5750600083138015610a265750600082135b801561096b5750828112156101635760405162461bcd60e51b81526004016101bc90610bd5565b803563ffffffff81168114610a6157600080fd5b919050565b60008060008060008060c08789031215610a7f57600080fd5b8635955060208701359450610a9660408801610a4d565b9350610aa460608801610a4d565b9250610ab260808801610a4d565b9150610ac060a08801610a4d565b90509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201610af757610af7610acc565b5060000390565b634e487b7160e01b600052601260045260246000fd5b600082610b2357610b23610afe565b600160ff1b821460001984141615610b3d57610b3d610acc565b500590565b6020808252600d908201526c6f75742d6f662d626f756e647360981b604082015260600190565b600082610b7857610b78610afe565b500790565b80820260008212600160ff1b84141615610b9957610b99610acc565b818105831482151761016357610163610acc565b8082018281126000831280158216821582161715610bcd57610bcd610acc565b505092915050565b6020808252600890820152676f766572666c6f7760c01b60408201526060019056fea26469706673582212201cac81319f1bc19d15bc3a02519b03e3559a9cf147525a96caa8cb800f74da2864736f6c634300081b0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c806349484d811461003a575b600080fd5b61004d610048366004610a66565b61005f565b60405190815260200160405180910390f35b6000806100728660030b8660030b61011c565b9050806000036100855787915050610112565b87600003610097576000915050610112565b60006100a98560030b8560030b61011c565b905060006100b8828a8c61013c565b9050600f6100c582610153565b13156100d657899350505050610112565b60006100ff6001607f1b6100fa866100f56100f087610ae2565b610169565b610882565b61089d565b905061010b818c6108d4565b9450505050505b9695505050505050565b600061013561012f846001607f1b610920565b83610988565b9392505050565b600061014b61012f8585610920565b949350505050565b60006101636001607f1b83610b14565b92915050565b60006101796101ff607c1b610ae2565b82121561018857506000919050565b8160000361019b57506001607f1b919050565b60008213156101c55760405162461bcd60e51b81526004016101bc90610b42565b60405180910390fd5b6000806101d66001607c1b85610b69565b91508190506001607f1b6101ea8280610b7d565b6101f49190610b14565b9050610208816710e1b3be415a0000610b7d565b6102129084610bad565b92506001607f1b6102238383610b7d565b61022d9190610b14565b9050610241816705a0913f6b1e0000610b7d565b61024b9084610bad565b92506001607f1b61025c8383610b7d565b6102669190610b14565b905061027a81670168244fdac78000610b7d565b6102849084610bad565b92506001607f1b6102958383610b7d565b61029f9190610b14565b90506102b281664807432bc18000610b7d565b6102bc9084610bad565b92506001607f1b6102cd8383610b7d565b6102d79190610b14565b90506102ea81660c0135dca04000610b7d565b6102f49084610bad565b92506001607f1b6103058383610b7d565b61030f9190610b14565b9050610322816601b707b1cdc000610b7d565b61032c9084610bad565b92506001607f1b61033d8383610b7d565b6103479190610b14565b9050610359816536e0f639b800610b7d565b6103639084610bad565b92506001607f1b6103748383610b7d565b61037e9190610b14565b905061039081650618fee9f800610b7d565b61039a9084610bad565b92506001607f1b6103ab8383610b7d565b6103b59190610b14565b90506103c681649c197dcc00610b7d565b6103d09084610bad565b92506001607f1b6103e18383610b7d565b6103eb9190610b14565b90506103fc81640e30dce400610b7d565b6104069084610bad565b92506001607f1b6104178383610b7d565b6104219190610b14565b90506104328164012ebd1300610b7d565b61043c9084610bad565b92506001607f1b61044d8383610b7d565b6104579190610b14565b9050610467816317499f00610b7d565b6104719084610bad565b92506001607f1b6104828383610b7d565b61048c9190610b14565b905061049c816301a9d480610b7d565b6104a69084610bad565b92506001607f1b6104b78383610b7d565b6104c19190610b14565b90506104d081621c6380610b7d565b6104da9084610bad565b92506001607f1b6104eb8383610b7d565b6104f59190610b14565b9050610504816201c638610b7d565b61050e9084610bad565b92506001607f1b61051f8383610b7d565b6105299190610b14565b905061053781611ab8610b7d565b6105419084610bad565b92506001607f1b6105528383610b7d565b61055c9190610b14565b905061056a8161017c610b7d565b6105749084610bad565b92506001607f1b6105858383610b7d565b61058f9190610b14565b905061059c816014610b7d565b6105a69084610bad565b92506001607f1b6105b78383610b7d565b6105c19190610b14565b90506105ce816001610b7d565b6105d89084610bad565b92506001607f1b826105f26721c3677c82b4000086610b14565b6105fc9190610bad565b6106069190610bad565b925061061184610ae2565b9350600160841b841615610657577243cbaf42a000812488fc5c220ad7b97bf6e99e61064a6cf1aaddd7742e56d32fb9f9974485610b7d565b6106549190610b14565b92505b600160831b84161561069c577105d27a9f51c31b7c2f8038212a057477999161068f6e0afe10820813d65dfe6a33c07f738f85610b7d565b6106999190610b14565b92505b600160821b8416156106e157701b4c902e273a58678d6d3bfdb93db96d026106d46f02582ab704279e8efd15e0265855c47a85610b7d565b6106de9190610b14565b92505b600160811b841615610726577003b1cc971a9bb5b9867477440d6d1577506107196f1152aaa3bf81cb9fdb76eae12d02957185610b7d565b6107239190610b14565b92505b600160801b84161561076b5770015bf0a8b1457695355fb8ac404e7a79e361075e6f2f16ac6c59de6f8d5d6f63c1482a7c8685610b7d565b6107689190610b14565b92505b6001607f1b8416156107af576fd3094c70f034de4b96ff7d5b6f99fcd86107a26f4da2cbf1be5827f9eb3ad1aa9866ebb385610b7d565b6107ac9190610b14565b92505b6001607e1b8416156107f3576fa45af1e1f40c333b3de1db4dd55f29a76107e66f63afbe7ab2082ba1a0ae5e4eb1b479dc85610b7d565b6107f09190610b14565b92505b6001607d1b841615610837576f910b022db7ae67ce76b441c27035c6a161082a6f70f5a893b608861e1f58934f97aea57d85610b7d565b6108349190610b14565b92505b6001607c1b84161561087b576f88415abbe9a76bead8d00cf112e4d4a861086e6f783eafef1c0a8f3978c7f81824d62ebf85610b7d565b6108789190610b14565b92505b5050919050565b60006001607f1b6108938484610920565b6101359190610b14565b6000600160ff1b82036108c25760405162461bcd60e51b81526004016101bc90610b42565b610135836108cf84610ae2565b6109f2565b6000808212156108f65760405162461bcd60e51b81526004016101bc90610b42565b60006109028484610920565b905060008113610916576000915050610163565b607f1c9392505050565b600082158061092d575081155b1561093a57506000610163565b508181028183828161094e5761094e610afe565b0514158061096b57508282828161096757610967610afe565b0514155b156101635760405162461bcd60e51b81526004016101bc90610bd5565b6000816000036109aa5760405162461bcd60e51b81526004016101bc90610bd5565b600160ff1b831480156109be575081600019145b156109db5760405162461bcd60e51b81526004016101bc90610bd5565b8183816109ea576109ea610afe565b059392505050565b818101600083128015610a055750600082125b8015610a1057508281135b8061096b5750600083138015610a265750600082135b801561096b5750828112156101635760405162461bcd60e51b81526004016101bc90610bd5565b803563ffffffff81168114610a6157600080fd5b919050565b60008060008060008060c08789031215610a7f57600080fd5b8635955060208701359450610a9660408801610a4d565b9350610aa460608801610a4d565b9250610ab260808801610a4d565b9150610ac060a08801610a4d565b90509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201610af757610af7610acc565b5060000390565b634e487b7160e01b600052601260045260246000fd5b600082610b2357610b23610afe565b600160ff1b821460001984141615610b3d57610b3d610acc565b500590565b6020808252600d908201526c6f75742d6f662d626f756e647360981b604082015260600190565b600082610b7857610b78610afe565b500790565b80820260008212600160ff1b84141615610b9957610b99610acc565b818105831482151761016357610163610acc565b8082018281126000831280158216821582161715610bcd57610bcd610acc565b505092915050565b6020808252600890820152676f766572666c6f7760c01b60408201526060019056fea26469706673582212201cac81319f1bc19d15bc3a02519b03e3559a9cf147525a96caa8cb800f74da2864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#HorizonStakingExtension.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#HorizonStakingExtension.json new file mode 100644 index 000000000..7cd249086 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/HorizonStakingExtension#HorizonStakingExtension.json @@ -0,0 +1,1263 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HorizonStakingExtension", + "sourceName": "contracts/staking/HorizonStakingExtension.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "address", + "name": "subgraphDataServiceAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyController", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyGovernor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "PPMMathInvalidPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "poi", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isPublic", + "type": "bool" + } + ], + "name": "AllocationClosed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "counterpart", + "type": "address" + } + ], + "name": "CounterpartStakingAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "assetHolder", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "protocolTax", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curationFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "queryFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "queryRebates", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delegationRewards", + "type": "uint256" + } + ], + "name": "RebateCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "StakeDelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredDelegationReturnedToDelegator", + "type": "event" + }, + { + "inputs": [], + "name": "__DEPRECATED_getThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "poi", + "type": "bytes32" + } + ], + "name": "closeAllocation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "getAllocation", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdAtEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "closedAtEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collectedFees", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "__DEPRECATED_effectiveAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerAllocatedToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "distributedRebates", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingExtension.Allocation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "getAllocationData", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "getAllocationState", + "outputs": [ + { + "internalType": "enum IHorizonStakingExtension.AllocationState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegatedTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.Delegation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + } + ], + "name": "getDelegationFeeCut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegationPool", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.DelegationPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getIdleStake", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "indexer", + "type": "address" + } + ], + "name": "getIndexerStakedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProviderTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProvision", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "createdAt", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxVerifierCutPending", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriodPending", + "type": "uint64" + } + ], + "internalType": "struct IHorizonStakingTypes.Provision", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getServiceProvider", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokensStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensProvisioned", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.ServiceProvider", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getSubgraphAllocatedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "getThawRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "next", + "type": "bytes32" + } + ], + "internalType": "struct IHorizonStakingTypes.ThawRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawRequestList", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "head", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tail", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "internalType": "struct LinkedList.List", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delegationRatio", + "type": "uint32" + } + ], + "name": "getTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "indexer", + "type": "address" + } + ], + "name": "hasStake", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "isActiveAllocation", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "isAllocation", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAllowedLockedVerifier", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDelegationSlashingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "counterpart", + "type": "address" + } + ], + "name": "setCounterpartStakingAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6101e060405234801561001157600080fd5b5060405161396738038061396783398101604081905261003091610411565b818181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610347565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610347565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610347565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610347565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610347565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610347565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610347565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610347565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610347565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b03166101c052506104b4915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038291815260200190565b602060405180830381865afa15801561039f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c39190610444565b9050826001600160a01b0382166103ee5760405163218f5add60e11b81526004016100749190610466565b5092915050565b80516001600160a01b038116811461040c57600080fd5b919050565b6000806040838503121561042457600080fd5b61042d836103f5565b915061043b602084016103f5565b90509250929050565b60006020828403121561045657600080fd5b61045f826103f5565b9392505050565b602081526000825180602084015260005b818110156104945760208186018101516040868401015201610477565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516133d761059060003960008181611c3601528181611e3601526123f00152600061205b015260005050600061178501526000818161213d0152818161280501526129080152600081816112c70152611b6f015260008181610bbf01528181610cbc01528181610ed601526116dc015260005050600050506000505060008181611044015281816111fa01528181612023015281816121b20152818161239a015281816124c2015261263201526133d76000f3fe6080604052600436106101f25760003560e01c806398c657dc1161010d578063b6363cf2116100a0578063e2e1e8e91161006f578063e2e1e8e914610a0b578063e73e14bf14610a38578063f1d60d6614610a70578063fb744cc014610a90578063fc54fb2714610ab057600080fd5b8063b6363cf2146108dd578063b7ca724114610927578063c0641994146109c1578063ccebcabb146109dc57600080fd5b8063a4c0ed36116100dc578063a4c0ed3614610837578063a784d49814610857578063ac9650d814610877578063ae4fe67a146108a457600080fd5b806398c657dc1461072d5780639ce7abe51461075a578063a212daf81461077a578063a2594d821461081757600080fd5b8063561285e411610185578063872d048911610154578063872d04891461064c5780638cc01c861461066c5780638d3c100a146106ed5780639054e3431461070d57600080fd5b8063561285e4146105a95780636a3ca383146105fc5780637573ef4f1461062c5780637a7664601461031157600080fd5b806325d9897e116101c157806325d9897e1461036957806339514ad21461047957806344c32a61146104ab57806355c85269146104cb57600080fd5b806308ce5f68146102495780630e0229231461027c5780631787e69f146103115780631ae720451461034757600080fd5b366102445760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b600080fd5b34801561025557600080fd5b50610269610264366004612bec565b610ac8565b6040519081526020015b60405180910390f35b34801561028857600080fd5b5061029c610297366004612c25565b610add565b604051610273919060006101208201905060018060a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b34801561031d57600080fd5b5061026961032c366004612c25565b6001600160a01b03166000908152600e602052604090205490565b34801561035357600080fd5b50610367610362366004612c25565b610bbd565b005b34801561037557600080fd5b5061046c610384366004612bec565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516102739190612c42565b34801561048557600080fd5b50601a546001600160401b03165b6040516001600160401b039091168152602001610273565b3480156104b757600080fd5b506103676104c6366004612cd2565b610cba565b3480156104d757600080fd5b506105776104e6366004612c25565b6001600160a01b039081166000908152600f602090815260408083208151610120810183528154909516808652600182015493860184905260028201549286018390526003820154606087015260048201546080870152600582015460a0870152600682015460c0870152600782015460e08701819052600890920154610100909601959095529394919390929091565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610273565b3480156105b557600080fd5b506105c96105c4366004612bec565b610d68565b60405161027391908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561060857600080fd5b5061061c610617366004612c25565b610df6565b6040519015158152602001610273565b34801561063857600080fd5b50610269610647366004612cfe565b610e1b565b34801561065857600080fd5b50610269610667366004612d4d565b610e7f565b34801561067857600080fd5b506106d2610687366004612c25565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b60408051825181526020928301519281019290925201610273565b3480156106f957600080fd5b50610367610708366004612d96565b610ed4565b34801561071957600080fd5b50610269610728366004612dbb565b6113a0565b34801561073957600080fd5b5061074d610748366004612c25565b611488565b6040516102739190612e11565b34801561076657600080fd5b50610367610775366004612e81565b611493565b34801561078657600080fd5b506105c9610795366004612dbb565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561082357600080fd5b50610367610832366004612c25565b6115be565b34801561084357600080fd5b50610367610852366004612ed5565b6116da565b34801561086357600080fd5b50610269610872366004612c25565b6118e7565b34801561088357600080fd5b50610897610892366004612f30565b6118f2565b6040516102739190612fc9565b3480156108b057600080fd5b5061061c6108bf366004612c25565b6001600160a01b031660009081526022602052604090205460ff1690565b3480156108e957600080fd5b5061061c6108f8366004612bec565b6001600160a01b0380821660009081526015602090815260408083209386168352929052205460ff1692915050565b34801561093357600080fd5b50610996610942366004613049565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b0316908201529181015190820152606001610273565b3480156109cd57600080fd5b50600d5463ffffffff16610493565b3480156109e857600080fd5b506109fc6109f7366004612dbb565b6119d9565b60405190518152602001610273565b348015610a1757600080fd5b50610269610a26366004613049565b60009081526010602052604090205490565b348015610a4457600080fd5b5061061c610a53366004612c25565b6001600160a01b03166000908152600e6020526040902054151590565b348015610a7c57600080fd5b5061061c610a8b366004612c25565b611a2b565b348015610a9c57600080fd5b50610269610aab366004612bec565b611a50565b348015610abc57600080fd5b5060205460ff1661061c565b6000610ad48383611a5c565b90505b92915050565b610b3860405180610120016040528060006001600160a01b0316815260200160008019168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b039081166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e08301526008015461010082015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190613062565b6001600160a01b0316336001600160a01b031614610c7057604051635d9044cd60e01b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0383169081179091556040517f690e9b982dc9aefaa1cfed186a2d2045a638013d658104102c9437235bee4b6090600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c919061307f565b15610d5a57604051632b37d9d160e21b815260040160405180910390fd5b610d648282611a94565b5050565b610d936040518060800160405280600081526020016000815260200160008152602001600081525090565b610dbe6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000610dca8585611e32565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b60006001610e0383611eb6565b6002811115610e1457610e14612dfb565b1492915050565b6001600160a01b038084166000908152601c60209081526040808320938616835292905290812081836002811115610e5557610e55612dfb565b6002811115610e6657610e66612dfb565b81526020019081526020016000205490505b9392505050565b600080610e8c8585611a5c565b90506000610e9a8686611f0f565b90506000610eae63ffffffff8616846130b7565b90506000610ebc8383611f3a565b9050610ec881856130ce565b98975050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061307f565b15610f7457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038116610fb35760405162461bcd60e51b815260206004820152600660248201526521616c6c6f6360d01b604482015260640161023b565b6000610fbe82611eb6565b90506000816002811115610fd457610fd4612dfb565b0361100c5760405162461bcd60e51b81526020600482015260086024820152670858dbdb1b1958dd60c21b604482015260640161023b565b8260000361101957505050565b6001600160a01b0382166000908152600f6020526040812060018101549091859080808061107333867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190611f51565b600d5461108e908690600160401b900463ffffffff1661200e565b935061109a84866130e1565b600d549095506110bb9087908790640100000000900463ffffffff16612047565b92506110c783866130e1565b94508487600501546110d991906130ce565b6005880155600287015460009015806110ff5750601954600160a01b900463ffffffff16155b6111ca5760058801546002890154600d546019546040516349484d8160e01b81526004810194909452602484019290925263ffffffff600160a01b80830482166044860152600160c01b928390048216606486015283048116608485015291041660a482015273__$8eb3cac1482a31d7a7f2cbe7dc8bdcd821$__906349484d819060c401602060405180830381865af41580156111a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c591906130f4565b6111cd565b60005b90506111dd81896008015461225a565b92506111e98387611f3a565b92506112296111f884886130e1565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690612274565b82156112915782886008015461123f91906130ce565b60088901558754611259906001600160a01b0316846122bc565b915061126582846130e1565b88546001600160a01b03908116600081815260176020526040902054929550611291928692161561234e565b5086546001600160a01b038a8116918891167ff5ded07502b6feba4c13b19a0c6646efd4b4119f439bcbd49076e4f0ed1eec4b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611323573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134791906130f4565b604080516001600160a01b039093168352602083019190915281018f9052606081018990526080810188905260a081018a905260c0810187905260e081018690526101000160405180910390a450505050505050505050565b6001600160a01b038084166000908152601e60209081526040808320868516845282528083209385168352929052908120600381015482036113e6576000915050610e78565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b801561147c576000818152601d602052604090206001810154426001600160401b039091161161146b5760028301546001840154825461145091906130b7565b61145a919061310d565b61146490856130ce565b9350611471565b5061147c565b600201549050611410565b50909695505050505050565b6000610ad782611eb6565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f89190613062565b6001600160a01b0316336001600160a01b0316146115585760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611586908690869060040161312f565b600060405180830381600087803b1580156115a057600080fd5b505af11580156115b4573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116239190613062565b6001600160a01b0316336001600160a01b0316146116835760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156116be57600080fd5b505af11580156116d2573d6000803e3d6000fd5b505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c919061307f565b1561177a57604051632b37d9d160e21b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117e15760405162461bcd60e51b815260206004820152600c60248201526b4f4e4c595f4741544557415960a01b604482015260640161023b565b6018546001600160a01b0385811691161461183e5760405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c315f5354414b494e475f5448524f5547485f4252494447450000604482015260640161023b565b60008061184d838501856131a4565b909250905060ff8216611882576000818060200190518101906118709190613255565b905061187c86826123c4565b506116d2565b60001960ff8316016118b0576000818060200190518101906118a491906132a2565b905061187c86826123d0565b60405162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f434f444560a01b604482015260640161023b565b6000610ad782612740565b604080516000815260208101909152606090826001600160401b0381111561191c5761191c61315e565b60405190808252806020026020018201604052801561194f57816020015b606081526020019060019003908161193a5790505b50915060005b838110156119d1576119ac3086868481811061197357611973613302565b90506020028101906119859190613318565b856040516020016119989392919061335e565b60405160208183030381529060405261278b565b8382815181106119be576119be613302565b6020908102919091010152600101611955565b505092915050565b6040805160208101909152600081526040805160208101909152600081526000611a038686611e32565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b600080611a3783611eb6565b6002811115611a4857611a48612dfb565b141592915050565b6000610ad48383611f0f565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610ad491906130e1565b6000611a9f83611eb6565b90506001816002811115611ab557611ab5612dfb565b14611aec5760405162461bcd60e51b81526020600482015260076024820152662161637469766560c81b604482015260640161023b565b6001600160a01b038381166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600801546101008201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef91906130f4565b608082018190526060820151600091611c079161225a565b9050600082600001516001600160a01b0316336001600160a01b03161480611c78575082516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600090815260156020908152604080832093909416825291909152205460ff165b600d54909150600160801b900463ffffffff1682111580611c9b57506040830151155b15611cd55780611cd55760405162461bcd60e51b8152602060048201526005602482015264042c2eae8d60db1b604482015260640161023b565b60808301516001600160a01b0387166000908152600f6020526040908190206004019190915583015115611db957808015611d0f57508415155b15611d2757611d22868460000151612801565b611d36565b611d3483602001516128e7565b505b60408084015184516001600160a01b03166000908152600e6020529190912060010154611d6391906130e1565b83516001600160a01b03166000908152600e602090815260408083206001019390935582860151818701518352601090915291902054611da391906130e1565b6020808501516000908152601090915260409020555b60208084015184516080808701516040808901518151928352958201959095523394810194909452606084018990528415908401526001600160a01b03808a16939116907ff6725dd105a6fc88bb79a6e4627f128577186c567a17c94818d201c2a4ce14039060a00160405180910390a4505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603611e8b57506001600160a01b0382166000908152601460205260409020610ad7565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610ad7565b6001600160a01b038082166000908152600f6020526040812080549192909116611ee35750600092915050565b600381015415801590611ef857506004810154155b15611f065750600192915050565b50600292915050565b600080611f1c8484611e32565b905080600501548160020154611f3291906130e1565b949350505050565b600081831115611f4a5781610ad4565b5090919050565b8015612009576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061307f565b6120095760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161023b565b505050565b60008061201b8484612975565b9050610ad4817f000000000000000000000000000000000000000000000000000000000000000061121a565b60008260000361205957506000610e78565b7f00000000000000000000000000000000000000000000000000000000000000006000831580159061209357506001600160a01b03821615155b90508080156121065750604051634c4ea0ed60e01b8152600481018790526001600160a01b03831690634c4ea0ed90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612106919061307f565b1561224e5760006121178686612975565b90508015612244576040516307470bfb60e21b8152600481018890526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631d1c2fec906024016020604051808303816000875af1158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa91906130f4565b506121e283827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906129c7565b60405163102ae65160e31b815260048101889052602481018290526001600160a01b03841690638157328890604401600060405180830381600087803b15801561222b57600080fd5b505af115801561223f573d6000803e3d6000fd5b505050505b9250610e78915050565b50600095945050505050565b600081831161226a576000610ad4565b610ad482846130e1565b8015610d6457604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156116be57600080fd5b6001600160a01b03821660009081526014602052604081206002810154829190158015906122fb57508054600160401b900463ffffffff16620f424010155b156123465780546000906123219063ffffffff600160401b9091048116908790612a0216565b905061232d81866130e1565b925082826002015461233f91906130ce565b6002830155505b509392505050565b8260000361235b57505050565b801561236b576120098284612a69565b6001600160a01b03808316600090815260176020526040902054166123be81156123955781612397565b835b857f00000000000000000000000000000000000000000000000000000000000000006121d2565b50505050565b80516120098184612a69565b80516001600160a01b039081166000908152601b602090815260408083207f0000000000000000000000000000000000000000000000000000000000000000909416835292905290812060030154600160601b90046001600160401b031690036124695760405162461bcd60e51b815260206004820152600a60248201526910b83937bb34b9b4b7b760b11b604482015260640161023b565b80516001600160a01b03908116600090815260146020908152604080832082860151909416835260048401909152902060028201541580156124bb575060038201541515806124bb5750600682015415155b156125b5577f0000000000000000000000000000000000000000000000000000000000000000602084015160405163a9059cbb60e01b81526001600160a01b0391821660048201526024810187905291169063a9059cbb906044016020604051808303816000875af1158015612535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612559919061307f565b5082602001516001600160a01b031683600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de866040516125a791815260200190565b60405180910390a350505050565b60008260020154600014806125d1575082600501548360020154145b61260757826005015483600201546125e991906130e1565b60038401546125f890876130b7565b612602919061310d565b612609565b845b905080158061261f5750670de0b6b3a764000085105b156126ae576126548460200151866121d27f000000000000000000000000000000000000000000000000000000000000000090565b83602001516001600160a01b031684600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de876040516126a191815260200190565b60405180910390a3612739565b8483600201546126be91906130ce565b600284015560038301546126d39082906130ce565b600384015581546126e59082906130ce565b82556020808501518551604080518981529384018590526001600160a01b039283169391909216917fcd0366dce5247d874ffc60a762aa7abbb82c1695bbb171609c1b8861e279eb73910160405180910390a35b5050505050565b6001600160a01b0381166000908152600e6020526040812060028101546001820154600483015492549192909161277791906130e1565b61278191906130e1565b610ad791906130e1565b6060600080846001600160a01b0316846040516127a89190613385565b600060405180830381855af49150503d80600081146127e3576040519150601f19603f3d011682016040523d82523d6000602084013e6127e8565b606091505b50915091506127f8858383612ae8565b95945050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000604051636dba849360e11b81526001600160a01b038581166004830152919091169063db750926906024016020604051808303816000875af115801561286e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289291906130f4565b9050806000036128a157505050565b60006128ad8383612b44565b905060006128bb82846130e1565b6001600160a01b038086166000908152601760205260409020549192506127399183918791161561234e565b6040516377561f0760e11b8152600481018290526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063eeac3e0e906024016020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad791906130f4565b600061298482620f4240101590565b82906129a657604051633dc311df60e01b815260040161023b91815260200190565b506129bd6129b783620f42406130e1565b84612a02565b610ad490846130e1565b80156120095760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401611f8e565b6000612a1183620f4240101590565b80612a245750612a2482620f4240101590565b83839091612a4e5760405163768bf0eb60e11b81526004810192909252602482015260440161023b565b50620f42409050612a5f83856130b7565b610ad4919061310d565b6001600160a01b0382166000908152600e6020526040902054612a8d9082906130ce565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290612adc9084815260200190565b60405180910390a25050565b606082612afd57612af882612bab565b610e78565b8151158015612b1457506001600160a01b0384163b155b15612b3d57604051639996b31560e01b81526001600160a01b038516600482015260240161023b565b5080610e78565b6001600160a01b0382166000908152601460205260408120600281015482919015801590612b8457508054640100000000900463ffffffff16620f424010155b156123465780546000906123219063ffffffff6401000000009091048116908790612a0216565b805115612bbb5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114612bd457600080fd5b60008060408385031215612bff57600080fd5b8235612c0a81612bd7565b91506020830135612c1a81612bd7565b809150509250929050565b600060208284031215612c3757600080fd5b8135610ad481612bd7565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151612cb060c084018263ffffffff169052565b5060e0830151612ccb60e08401826001600160401b03169052565b5092915050565b60008060408385031215612ce557600080fd5b8235612cf081612bd7565b946020939093013593505050565b600080600060608486031215612d1357600080fd5b8335612d1e81612bd7565b92506020840135612d2e81612bd7565b9150604084013560038110612d4257600080fd5b809150509250925092565b600080600060608486031215612d6257600080fd5b8335612d6d81612bd7565b92506020840135612d7d81612bd7565b9150604084013563ffffffff81168114612d4257600080fd5b60008060408385031215612da957600080fd5b823591506020830135612c1a81612bd7565b600080600060608486031215612dd057600080fd5b8335612ddb81612bd7565b92506020840135612deb81612bd7565b91506040840135612d4281612bd7565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612e3357634e487b7160e01b600052602160045260246000fd5b91905290565b60008083601f840112612e4b57600080fd5b5081356001600160401b03811115612e6257600080fd5b602083019150836020828501011115612e7a57600080fd5b9250929050565b600080600060408486031215612e9657600080fd5b8335612ea181612bd7565b925060208401356001600160401b03811115612ebc57600080fd5b612ec886828701612e39565b9497909650939450505050565b60008060008060608587031215612eeb57600080fd5b8435612ef681612bd7565b93506020850135925060408501356001600160401b03811115612f1857600080fd5b612f2487828801612e39565b95989497509550505050565b60008060208385031215612f4357600080fd5b82356001600160401b03811115612f5957600080fd5b8301601f81018513612f6a57600080fd5b80356001600160401b03811115612f8057600080fd5b8560208260051b8401011115612f9557600080fd5b6020919091019590945092505050565b60005b83811015612fc0578181015183820152602001612fa8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561303d57603f198786030184528151805180875261301a816020890160208501612fa5565b601f01601f19169590950160209081019550938401939190910190600101612ff1565b50929695505050505050565b60006020828403121561305b57600080fd5b5035919050565b60006020828403121561307457600080fd5b8151610ad481612bd7565b60006020828403121561309157600080fd5b81518015158114610ad457600080fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610ad757610ad76130a1565b80820180821115610ad757610ad76130a1565b81810381811115610ad757610ad76130a1565b60006020828403121561310657600080fd5b5051919050565b60008261312a57634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561319c5761319c61315e565b604052919050565b600080604083850312156131b757600080fd5b823560ff811681146131c857600080fd5b915060208301356001600160401b038111156131e357600080fd5b8301601f810185136131f457600080fd5b80356001600160401b0381111561320d5761320d61315e565b613220601f8201601f1916602001613174565b81815286602083850101111561323557600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000602082840312801561326857600080fd5b50604051602081016001600160401b038111828210171561328b5761328b61315e565b604052825161329981612bd7565b81529392505050565b600060408284031280156132b557600080fd5b50604080519081016001600160401b03811182821017156132d8576132d861315e565b60405282516132e681612bd7565b815260208301516132f681612bd7565b60208201529392505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261332f57600080fd5b8301803591506001600160401b0382111561334957600080fd5b602001915036819003821315612e7a57600080fd5b82848237600083820160008152835161337b818360208801612fa5565b0195945050505050565b60008251613397818460208701612fa5565b919091019291505056fea264697066735822122038ad83d20c219353421029f1ad8c4f7667d5f0e86af1579c64603bb56827d86064736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106101f25760003560e01c806398c657dc1161010d578063b6363cf2116100a0578063e2e1e8e91161006f578063e2e1e8e914610a0b578063e73e14bf14610a38578063f1d60d6614610a70578063fb744cc014610a90578063fc54fb2714610ab057600080fd5b8063b6363cf2146108dd578063b7ca724114610927578063c0641994146109c1578063ccebcabb146109dc57600080fd5b8063a4c0ed36116100dc578063a4c0ed3614610837578063a784d49814610857578063ac9650d814610877578063ae4fe67a146108a457600080fd5b806398c657dc1461072d5780639ce7abe51461075a578063a212daf81461077a578063a2594d821461081757600080fd5b8063561285e411610185578063872d048911610154578063872d04891461064c5780638cc01c861461066c5780638d3c100a146106ed5780639054e3431461070d57600080fd5b8063561285e4146105a95780636a3ca383146105fc5780637573ef4f1461062c5780637a7664601461031157600080fd5b806325d9897e116101c157806325d9897e1461036957806339514ad21461047957806344c32a61146104ab57806355c85269146104cb57600080fd5b806308ce5f68146102495780630e0229231461027c5780631787e69f146103115780631ae720451461034757600080fd5b366102445760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b600080fd5b34801561025557600080fd5b50610269610264366004612bec565b610ac8565b6040519081526020015b60405180910390f35b34801561028857600080fd5b5061029c610297366004612c25565b610add565b604051610273919060006101208201905060018060a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b34801561031d57600080fd5b5061026961032c366004612c25565b6001600160a01b03166000908152600e602052604090205490565b34801561035357600080fd5b50610367610362366004612c25565b610bbd565b005b34801561037557600080fd5b5061046c610384366004612bec565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516102739190612c42565b34801561048557600080fd5b50601a546001600160401b03165b6040516001600160401b039091168152602001610273565b3480156104b757600080fd5b506103676104c6366004612cd2565b610cba565b3480156104d757600080fd5b506105776104e6366004612c25565b6001600160a01b039081166000908152600f602090815260408083208151610120810183528154909516808652600182015493860184905260028201549286018390526003820154606087015260048201546080870152600582015460a0870152600682015460c0870152600782015460e08701819052600890920154610100909601959095529394919390929091565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610273565b3480156105b557600080fd5b506105c96105c4366004612bec565b610d68565b60405161027391908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561060857600080fd5b5061061c610617366004612c25565b610df6565b6040519015158152602001610273565b34801561063857600080fd5b50610269610647366004612cfe565b610e1b565b34801561065857600080fd5b50610269610667366004612d4d565b610e7f565b34801561067857600080fd5b506106d2610687366004612c25565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b60408051825181526020928301519281019290925201610273565b3480156106f957600080fd5b50610367610708366004612d96565b610ed4565b34801561071957600080fd5b50610269610728366004612dbb565b6113a0565b34801561073957600080fd5b5061074d610748366004612c25565b611488565b6040516102739190612e11565b34801561076657600080fd5b50610367610775366004612e81565b611493565b34801561078657600080fd5b506105c9610795366004612dbb565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561082357600080fd5b50610367610832366004612c25565b6115be565b34801561084357600080fd5b50610367610852366004612ed5565b6116da565b34801561086357600080fd5b50610269610872366004612c25565b6118e7565b34801561088357600080fd5b50610897610892366004612f30565b6118f2565b6040516102739190612fc9565b3480156108b057600080fd5b5061061c6108bf366004612c25565b6001600160a01b031660009081526022602052604090205460ff1690565b3480156108e957600080fd5b5061061c6108f8366004612bec565b6001600160a01b0380821660009081526015602090815260408083209386168352929052205460ff1692915050565b34801561093357600080fd5b50610996610942366004613049565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b0316908201529181015190820152606001610273565b3480156109cd57600080fd5b50600d5463ffffffff16610493565b3480156109e857600080fd5b506109fc6109f7366004612dbb565b6119d9565b60405190518152602001610273565b348015610a1757600080fd5b50610269610a26366004613049565b60009081526010602052604090205490565b348015610a4457600080fd5b5061061c610a53366004612c25565b6001600160a01b03166000908152600e6020526040902054151590565b348015610a7c57600080fd5b5061061c610a8b366004612c25565b611a2b565b348015610a9c57600080fd5b50610269610aab366004612bec565b611a50565b348015610abc57600080fd5b5060205460ff1661061c565b6000610ad48383611a5c565b90505b92915050565b610b3860405180610120016040528060006001600160a01b0316815260200160008019168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b039081166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e08301526008015461010082015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190613062565b6001600160a01b0316336001600160a01b031614610c7057604051635d9044cd60e01b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0383169081179091556040517f690e9b982dc9aefaa1cfed186a2d2045a638013d658104102c9437235bee4b6090600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c919061307f565b15610d5a57604051632b37d9d160e21b815260040160405180910390fd5b610d648282611a94565b5050565b610d936040518060800160405280600081526020016000815260200160008152602001600081525090565b610dbe6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000610dca8585611e32565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b60006001610e0383611eb6565b6002811115610e1457610e14612dfb565b1492915050565b6001600160a01b038084166000908152601c60209081526040808320938616835292905290812081836002811115610e5557610e55612dfb565b6002811115610e6657610e66612dfb565b81526020019081526020016000205490505b9392505050565b600080610e8c8585611a5c565b90506000610e9a8686611f0f565b90506000610eae63ffffffff8616846130b7565b90506000610ebc8383611f3a565b9050610ec881856130ce565b98975050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061307f565b15610f7457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038116610fb35760405162461bcd60e51b815260206004820152600660248201526521616c6c6f6360d01b604482015260640161023b565b6000610fbe82611eb6565b90506000816002811115610fd457610fd4612dfb565b0361100c5760405162461bcd60e51b81526020600482015260086024820152670858dbdb1b1958dd60c21b604482015260640161023b565b8260000361101957505050565b6001600160a01b0382166000908152600f6020526040812060018101549091859080808061107333867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190611f51565b600d5461108e908690600160401b900463ffffffff1661200e565b935061109a84866130e1565b600d549095506110bb9087908790640100000000900463ffffffff16612047565b92506110c783866130e1565b94508487600501546110d991906130ce565b6005880155600287015460009015806110ff5750601954600160a01b900463ffffffff16155b6111ca5760058801546002890154600d546019546040516349484d8160e01b81526004810194909452602484019290925263ffffffff600160a01b80830482166044860152600160c01b928390048216606486015283048116608485015291041660a482015273__$8eb3cac1482a31d7a7f2cbe7dc8bdcd821$__906349484d819060c401602060405180830381865af41580156111a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c591906130f4565b6111cd565b60005b90506111dd81896008015461225a565b92506111e98387611f3a565b92506112296111f884886130e1565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690612274565b82156112915782886008015461123f91906130ce565b60088901558754611259906001600160a01b0316846122bc565b915061126582846130e1565b88546001600160a01b03908116600081815260176020526040902054929550611291928692161561234e565b5086546001600160a01b038a8116918891167ff5ded07502b6feba4c13b19a0c6646efd4b4119f439bcbd49076e4f0ed1eec4b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611323573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134791906130f4565b604080516001600160a01b039093168352602083019190915281018f9052606081018990526080810188905260a081018a905260c0810187905260e081018690526101000160405180910390a450505050505050505050565b6001600160a01b038084166000908152601e60209081526040808320868516845282528083209385168352929052908120600381015482036113e6576000915050610e78565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b801561147c576000818152601d602052604090206001810154426001600160401b039091161161146b5760028301546001840154825461145091906130b7565b61145a919061310d565b61146490856130ce565b9350611471565b5061147c565b600201549050611410565b50909695505050505050565b6000610ad782611eb6565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f89190613062565b6001600160a01b0316336001600160a01b0316146115585760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611586908690869060040161312f565b600060405180830381600087803b1580156115a057600080fd5b505af11580156115b4573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116239190613062565b6001600160a01b0316336001600160a01b0316146116835760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156116be57600080fd5b505af11580156116d2573d6000803e3d6000fd5b505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c919061307f565b1561177a57604051632b37d9d160e21b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117e15760405162461bcd60e51b815260206004820152600c60248201526b4f4e4c595f4741544557415960a01b604482015260640161023b565b6018546001600160a01b0385811691161461183e5760405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c315f5354414b494e475f5448524f5547485f4252494447450000604482015260640161023b565b60008061184d838501856131a4565b909250905060ff8216611882576000818060200190518101906118709190613255565b905061187c86826123c4565b506116d2565b60001960ff8316016118b0576000818060200190518101906118a491906132a2565b905061187c86826123d0565b60405162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f434f444560a01b604482015260640161023b565b6000610ad782612740565b604080516000815260208101909152606090826001600160401b0381111561191c5761191c61315e565b60405190808252806020026020018201604052801561194f57816020015b606081526020019060019003908161193a5790505b50915060005b838110156119d1576119ac3086868481811061197357611973613302565b90506020028101906119859190613318565b856040516020016119989392919061335e565b60405160208183030381529060405261278b565b8382815181106119be576119be613302565b6020908102919091010152600101611955565b505092915050565b6040805160208101909152600081526040805160208101909152600081526000611a038686611e32565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b600080611a3783611eb6565b6002811115611a4857611a48612dfb565b141592915050565b6000610ad48383611f0f565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610ad491906130e1565b6000611a9f83611eb6565b90506001816002811115611ab557611ab5612dfb565b14611aec5760405162461bcd60e51b81526020600482015260076024820152662161637469766560c81b604482015260640161023b565b6001600160a01b038381166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600801546101008201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef91906130f4565b608082018190526060820151600091611c079161225a565b9050600082600001516001600160a01b0316336001600160a01b03161480611c78575082516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600090815260156020908152604080832093909416825291909152205460ff165b600d54909150600160801b900463ffffffff1682111580611c9b57506040830151155b15611cd55780611cd55760405162461bcd60e51b8152602060048201526005602482015264042c2eae8d60db1b604482015260640161023b565b60808301516001600160a01b0387166000908152600f6020526040908190206004019190915583015115611db957808015611d0f57508415155b15611d2757611d22868460000151612801565b611d36565b611d3483602001516128e7565b505b60408084015184516001600160a01b03166000908152600e6020529190912060010154611d6391906130e1565b83516001600160a01b03166000908152600e602090815260408083206001019390935582860151818701518352601090915291902054611da391906130e1565b6020808501516000908152601090915260409020555b60208084015184516080808701516040808901518151928352958201959095523394810194909452606084018990528415908401526001600160a01b03808a16939116907ff6725dd105a6fc88bb79a6e4627f128577186c567a17c94818d201c2a4ce14039060a00160405180910390a4505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603611e8b57506001600160a01b0382166000908152601460205260409020610ad7565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610ad7565b6001600160a01b038082166000908152600f6020526040812080549192909116611ee35750600092915050565b600381015415801590611ef857506004810154155b15611f065750600192915050565b50600292915050565b600080611f1c8484611e32565b905080600501548160020154611f3291906130e1565b949350505050565b600081831115611f4a5781610ad4565b5090919050565b8015612009576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061307f565b6120095760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161023b565b505050565b60008061201b8484612975565b9050610ad4817f000000000000000000000000000000000000000000000000000000000000000061121a565b60008260000361205957506000610e78565b7f00000000000000000000000000000000000000000000000000000000000000006000831580159061209357506001600160a01b03821615155b90508080156121065750604051634c4ea0ed60e01b8152600481018790526001600160a01b03831690634c4ea0ed90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612106919061307f565b1561224e5760006121178686612975565b90508015612244576040516307470bfb60e21b8152600481018890526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631d1c2fec906024016020604051808303816000875af1158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa91906130f4565b506121e283827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906129c7565b60405163102ae65160e31b815260048101889052602481018290526001600160a01b03841690638157328890604401600060405180830381600087803b15801561222b57600080fd5b505af115801561223f573d6000803e3d6000fd5b505050505b9250610e78915050565b50600095945050505050565b600081831161226a576000610ad4565b610ad482846130e1565b8015610d6457604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156116be57600080fd5b6001600160a01b03821660009081526014602052604081206002810154829190158015906122fb57508054600160401b900463ffffffff16620f424010155b156123465780546000906123219063ffffffff600160401b9091048116908790612a0216565b905061232d81866130e1565b925082826002015461233f91906130ce565b6002830155505b509392505050565b8260000361235b57505050565b801561236b576120098284612a69565b6001600160a01b03808316600090815260176020526040902054166123be81156123955781612397565b835b857f00000000000000000000000000000000000000000000000000000000000000006121d2565b50505050565b80516120098184612a69565b80516001600160a01b039081166000908152601b602090815260408083207f0000000000000000000000000000000000000000000000000000000000000000909416835292905290812060030154600160601b90046001600160401b031690036124695760405162461bcd60e51b815260206004820152600a60248201526910b83937bb34b9b4b7b760b11b604482015260640161023b565b80516001600160a01b03908116600090815260146020908152604080832082860151909416835260048401909152902060028201541580156124bb575060038201541515806124bb5750600682015415155b156125b5577f0000000000000000000000000000000000000000000000000000000000000000602084015160405163a9059cbb60e01b81526001600160a01b0391821660048201526024810187905291169063a9059cbb906044016020604051808303816000875af1158015612535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612559919061307f565b5082602001516001600160a01b031683600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de866040516125a791815260200190565b60405180910390a350505050565b60008260020154600014806125d1575082600501548360020154145b61260757826005015483600201546125e991906130e1565b60038401546125f890876130b7565b612602919061310d565b612609565b845b905080158061261f5750670de0b6b3a764000085105b156126ae576126548460200151866121d27f000000000000000000000000000000000000000000000000000000000000000090565b83602001516001600160a01b031684600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de876040516126a191815260200190565b60405180910390a3612739565b8483600201546126be91906130ce565b600284015560038301546126d39082906130ce565b600384015581546126e59082906130ce565b82556020808501518551604080518981529384018590526001600160a01b039283169391909216917fcd0366dce5247d874ffc60a762aa7abbb82c1695bbb171609c1b8861e279eb73910160405180910390a35b5050505050565b6001600160a01b0381166000908152600e6020526040812060028101546001820154600483015492549192909161277791906130e1565b61278191906130e1565b610ad791906130e1565b6060600080846001600160a01b0316846040516127a89190613385565b600060405180830381855af49150503d80600081146127e3576040519150601f19603f3d011682016040523d82523d6000602084013e6127e8565b606091505b50915091506127f8858383612ae8565b95945050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000604051636dba849360e11b81526001600160a01b038581166004830152919091169063db750926906024016020604051808303816000875af115801561286e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289291906130f4565b9050806000036128a157505050565b60006128ad8383612b44565b905060006128bb82846130e1565b6001600160a01b038086166000908152601760205260409020549192506127399183918791161561234e565b6040516377561f0760e11b8152600481018290526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063eeac3e0e906024016020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad791906130f4565b600061298482620f4240101590565b82906129a657604051633dc311df60e01b815260040161023b91815260200190565b506129bd6129b783620f42406130e1565b84612a02565b610ad490846130e1565b80156120095760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401611f8e565b6000612a1183620f4240101590565b80612a245750612a2482620f4240101590565b83839091612a4e5760405163768bf0eb60e11b81526004810192909252602482015260440161023b565b50620f42409050612a5f83856130b7565b610ad4919061310d565b6001600160a01b0382166000908152600e6020526040902054612a8d9082906130ce565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290612adc9084815260200190565b60405180910390a25050565b606082612afd57612af882612bab565b610e78565b8151158015612b1457506001600160a01b0384163b155b15612b3d57604051639996b31560e01b81526001600160a01b038516600482015260240161023b565b5080610e78565b6001600160a01b0382166000908152601460205260408120600281015482919015801590612b8457508054640100000000900463ffffffff16620f424010155b156123465780546000906123219063ffffffff6401000000009091048116908790612a0216565b805115612bbb5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114612bd457600080fd5b60008060408385031215612bff57600080fd5b8235612c0a81612bd7565b91506020830135612c1a81612bd7565b809150509250929050565b600060208284031215612c3757600080fd5b8135610ad481612bd7565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151612cb060c084018263ffffffff169052565b5060e0830151612ccb60e08401826001600160401b03169052565b5092915050565b60008060408385031215612ce557600080fd5b8235612cf081612bd7565b946020939093013593505050565b600080600060608486031215612d1357600080fd5b8335612d1e81612bd7565b92506020840135612d2e81612bd7565b9150604084013560038110612d4257600080fd5b809150509250925092565b600080600060608486031215612d6257600080fd5b8335612d6d81612bd7565b92506020840135612d7d81612bd7565b9150604084013563ffffffff81168114612d4257600080fd5b60008060408385031215612da957600080fd5b823591506020830135612c1a81612bd7565b600080600060608486031215612dd057600080fd5b8335612ddb81612bd7565b92506020840135612deb81612bd7565b91506040840135612d4281612bd7565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612e3357634e487b7160e01b600052602160045260246000fd5b91905290565b60008083601f840112612e4b57600080fd5b5081356001600160401b03811115612e6257600080fd5b602083019150836020828501011115612e7a57600080fd5b9250929050565b600080600060408486031215612e9657600080fd5b8335612ea181612bd7565b925060208401356001600160401b03811115612ebc57600080fd5b612ec886828701612e39565b9497909650939450505050565b60008060008060608587031215612eeb57600080fd5b8435612ef681612bd7565b93506020850135925060408501356001600160401b03811115612f1857600080fd5b612f2487828801612e39565b95989497509550505050565b60008060208385031215612f4357600080fd5b82356001600160401b03811115612f5957600080fd5b8301601f81018513612f6a57600080fd5b80356001600160401b03811115612f8057600080fd5b8560208260051b8401011115612f9557600080fd5b6020919091019590945092505050565b60005b83811015612fc0578181015183820152602001612fa8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561303d57603f198786030184528151805180875261301a816020890160208501612fa5565b601f01601f19169590950160209081019550938401939190910190600101612ff1565b50929695505050505050565b60006020828403121561305b57600080fd5b5035919050565b60006020828403121561307457600080fd5b8151610ad481612bd7565b60006020828403121561309157600080fd5b81518015158114610ad457600080fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610ad757610ad76130a1565b80820180821115610ad757610ad76130a1565b81810381811115610ad757610ad76130a1565b60006020828403121561310657600080fd5b5051919050565b60008261312a57634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561319c5761319c61315e565b604052919050565b600080604083850312156131b757600080fd5b823560ff811681146131c857600080fd5b915060208301356001600160401b038111156131e357600080fd5b8301601f810185136131f457600080fd5b80356001600160401b0381111561320d5761320d61315e565b613220601f8201601f1916602001613174565b81815286602083850101111561323557600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000602082840312801561326857600080fd5b50604051602081016001600160401b038111828210171561328b5761328b61315e565b604052825161329981612bd7565b81529392505050565b600060408284031280156132b557600080fd5b50604080519081016001600160401b03811182821017156132d8576132d861315e565b60405282516132e681612bd7565b815260208301516132f681612bd7565b60208201529392505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261332f57600080fd5b8301803591506001600160401b0382111561334957600080fd5b602001915036819003821315612e7a57600080fd5b82848237600083820160008152835161337b818360208801612fa5565b0195945050505050565b60008251613397818460208701612fa5565b919091019291505056fea264697066735822122038ad83d20c219353421029f1ad8c4f7667d5f0e86af1579c64603bb56827d86064736f6c634300081b0033", + "linkReferences": { + "contracts/staking/libraries/ExponentialRebates.sol": { + "ExponentialRebates": [ + { + "length": 20, + "start": 5879 + } + ] + } + }, + "deployedLinkReferences": { + "contracts/staking/libraries/ExponentialRebates.sol": { + "ExponentialRebates": [ + { + "length": 20, + "start": 4455 + } + ] + } + } +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow.json new file mode 100644 index 000000000..4f10cc208 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow.json @@ -0,0 +1,769 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymentsEscrow", + "sourceName": "contracts/payments/PaymentsEscrow.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "revokeCollectorThawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawEscrowThawingPeriod", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balanceBefore", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInconsistentCollection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAllowance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBalance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowNotThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "PaymentsEscrowStillThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "thawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxThawingPeriod", + "type": "uint256" + } + ], + "name": "PaymentsEscrowThawingPeriodTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "AuthorizedCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "CancelThaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "CancelThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "EscrowCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "RevokeCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "Thaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "ThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVOKE_COLLECTOR_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WITHDRAW_ESCROW_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + } + ], + "name": "approveCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "authorizedCollectors", + "outputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "cancelThawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "escrowAccounts", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + } + ], + "name": "revokeCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "thawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b506040516120c73803806120c78339810160408190526100309161046b565b826001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b2906103a1565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e5906103a1565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e906103a1565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b6020820152610158906103a1565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b6020820152610190906103a1565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb906103a1565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b6020820152610209906103a1565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b6020820152610245906103a1565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a906103a1565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450816276a7008082111561035c57604051635c0f65a160e01b815260048101929092526024820152604401610071565b508190506276a7008082111561038e57604051635c0f65a160e01b815260048101929092526024820152604401610071565b50506101c0919091526101e05250610510565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103dc91815260200190565b602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d91906104a0565b9050826001600160a01b0382166104485760405163218f5add60e11b815260040161007191906104c2565b5092915050565b80516001600160a01b038116811461046657600080fd5b919050565b60008060006060848603121561048057600080fd5b6104898461044f565b602085015160409095015190969495509392505050565b6000602082840312156104b257600080fd5b6104bb8261044f565b9392505050565b602081526000825180602084015260005b818110156104f057602081860181015160408684010152016104d3565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051611ad26105f5600039600081816101e00152610abb015260008181610193015261039d01526000505060005050600050506000505060005050600081816102fa0152818161041601528181610589015281816106380152818161076e0152818161094901528181610b2d01528181610d71015261131b01526000505060008181610fa6015261104e015260005050600081816108da01528181610eea01528181610f77015281816110c401526114130152611ad26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json new file mode 100644 index 000000000..4f10cc208 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json @@ -0,0 +1,769 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymentsEscrow", + "sourceName": "contracts/payments/PaymentsEscrow.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "revokeCollectorThawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawEscrowThawingPeriod", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balanceBefore", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInconsistentCollection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAllowance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBalance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowNotThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "PaymentsEscrowStillThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "thawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxThawingPeriod", + "type": "uint256" + } + ], + "name": "PaymentsEscrowThawingPeriodTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "AuthorizedCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "CancelThaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "CancelThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "EscrowCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "RevokeCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "Thaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "ThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVOKE_COLLECTOR_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WITHDRAW_ESCROW_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + } + ], + "name": "approveCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "authorizedCollectors", + "outputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "cancelThawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "escrowAccounts", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + } + ], + "name": "revokeCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "thawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b506040516120c73803806120c78339810160408190526100309161046b565b826001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b2906103a1565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e5906103a1565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e906103a1565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b6020820152610158906103a1565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b6020820152610190906103a1565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb906103a1565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b6020820152610209906103a1565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b6020820152610245906103a1565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a906103a1565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450816276a7008082111561035c57604051635c0f65a160e01b815260048101929092526024820152604401610071565b508190506276a7008082111561038e57604051635c0f65a160e01b815260048101929092526024820152604401610071565b50506101c0919091526101e05250610510565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103dc91815260200190565b602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d91906104a0565b9050826001600160a01b0382166104485760405163218f5add60e11b815260040161007191906104c2565b5092915050565b80516001600160a01b038116811461046657600080fd5b919050565b60008060006060848603121561048057600080fd5b6104898461044f565b602085015160409095015190969495509392505050565b6000602082840312156104b257600080fd5b6104bb8261044f565b9392505050565b602081526000825180602084015260005b818110156104f057602081860181015160408684010152016104d3565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051611ad26105f5600039600081816101e00152610abb015260008181610193015261039d01526000505060005050600050506000505060005050600081816102fa0152818161041601528181610589015281816106380152818161076e0152818161094901528181610b2d01528181610d71015261131b01526000505060008181610fa6015261104e015260005050600081816108da01528181610eea01528181610f77015281816110c401526114130152611ad26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#GraphProxy.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager.json new file mode 100644 index 000000000..87ac4c282 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager.json @@ -0,0 +1,635 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RewardsManager", + "sourceName": "contracts/rewards/RewardsManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardsAssigned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "RewardsDenied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sinceBlock", + "type": "uint256" + } + ], + "name": "RewardsDenylistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldSubgraphService", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [], + "name": "accRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accRewardsPerSignalLastBlockUpdated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "name": "calcRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "denylist", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsForSubgraph", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsPerAllocatedToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNewRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "getRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isDenied", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "issuancePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumSubgraphSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphAllocationUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphSignalUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "_deny", + "type": "bool" + } + ], + "name": "setDenied", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_subgraphDeploymentID", + "type": "bytes32[]" + }, + { + "internalType": "bool[]", + "name": "_deny", + "type": "bool[]" + } + ], + "name": "setDeniedMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_issuancePerBlock", + "type": "uint256" + } + ], + "name": "setIssuancePerBlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumSubgraphSignal", + "type": "uint256" + } + ], + "name": "setMinimumSubgraphSignal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphAvailabilityOracle", + "type": "address" + } + ], + "name": "setSubgraphAvailabilityOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphAvailabilityOracle", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "contract IRewardsIssuer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "subgraphs", + "outputs": [ + { + "internalType": "uint256", + "name": "accRewardsForSubgraph", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsForSubgraphSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerSignalSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "takeRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051611eb861017360003980610fe1525080610fb8525080610f8f528061194f525080610f6652806116d2525080610f3d525080610f14525080610eeb52806115165250611eb86000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager_Instance.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager_Instance.json new file mode 100644 index 000000000..87ac4c282 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/RewardsManager#RewardsManager_Instance.json @@ -0,0 +1,635 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RewardsManager", + "sourceName": "contracts/rewards/RewardsManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardsAssigned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "RewardsDenied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sinceBlock", + "type": "uint256" + } + ], + "name": "RewardsDenylistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldSubgraphService", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [], + "name": "accRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accRewardsPerSignalLastBlockUpdated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "name": "calcRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "denylist", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsForSubgraph", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsPerAllocatedToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNewRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "getRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isDenied", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "issuancePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumSubgraphSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphAllocationUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphSignalUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "_deny", + "type": "bool" + } + ], + "name": "setDenied", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_subgraphDeploymentID", + "type": "bytes32[]" + }, + { + "internalType": "bool[]", + "name": "_deny", + "type": "bool[]" + } + ], + "name": "setDeniedMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_issuancePerBlock", + "type": "uint256" + } + ], + "name": "setIssuancePerBlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumSubgraphSignal", + "type": "uint256" + } + ], + "name": "setMinimumSubgraphSignal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphAvailabilityOracle", + "type": "address" + } + ], + "name": "setSubgraphAvailabilityOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphAvailabilityOracle", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "contract IRewardsIssuer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "subgraphs", + "outputs": [ + { + "internalType": "uint256", + "name": "accRewardsForSubgraph", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsForSubgraphSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerSignalSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "takeRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051611eb861017360003980610fe1525080610fb8525080610f8f528061194f525080610f6652806116d2525080610f3d525080610f14525080610eeb52806115165250611eb86000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/artifacts/TAPCollector#TAPCollector.json b/packages/horizon/ignition/deployments/chain-11155111/artifacts/TAPCollector#TAPCollector.json new file mode 100644 index 000000000..94f0189f7 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/artifacts/TAPCollector#TAPCollector.json @@ -0,0 +1,450 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TAPCollector", + "sourceName": "contracts/payments/collectors/TAPCollector.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "eip712Name", + "type": "string" + }, + { + "internalType": "string", + "name": "eip712Version", + "type": "string" + }, + { + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + } + ], + "name": "TAPCollectorCallerNotDataService", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensCollected", + "type": "uint256" + } + ], + "name": "TAPCollectorInconsistentRAVTokens", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensReceiver", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "PaymentCollected", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "collect", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timestampNs", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "valueAggregate", + "type": "uint128" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "internalType": "struct ITAPCollector.ReceiptAggregateVoucher", + "name": "rav", + "type": "tuple" + } + ], + "name": "encodeRAV", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timestampNs", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "valueAggregate", + "type": "uint128" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "internalType": "struct ITAPCollector.ReceiptAggregateVoucher", + "name": "rav", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct ITAPCollector.SignedRAV", + "name": "signedRAV", + "type": "tuple" + } + ], + "name": "recoverRAVSigner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "tokensCollected", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6102a060405234801561001157600080fd5b506040516119ae3803806119ae833981016040819052610030916105d9565b80838361003e8260006103db565b6101205261004d8160016103db565b61014052815160208084019190912060e052815190820120610100524660a0526100da60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c0526001600160a01b03811661012c5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101e05260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526101649061040e565b6001600160a01b0316610160526040805180820190915260078152665374616b696e6760c81b60208201526101989061040e565b6001600160a01b03166101805260408051808201909152600d81526c47726170685061796d656e747360981b60208201526101d29061040e565b6001600160a01b03166101a05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261020d9061040e565b6001600160a01b03166101c05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b60208201526102469061040e565b6001600160a01b03166102005260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526102819061040e565b6001600160a01b0316610220526040805180820190915260118152704772617068546f6b656e4761746577617960781b60208201526102bf9061040e565b6001600160a01b03166102405260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b60208201526102fb9061040e565b6001600160a01b03166102605260408051808201909152600881526721bab930ba34b7b760c11b60208201526103309061040e565b6001600160a01b039081166102808190526101e05161018051610160516101a0516101c0516102005161022051610240516102605160408051968c168752948b166020870152928a1685850152908916606085015288166080840152871660a083015260c0820195909552935192851694918216939116917fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a439181900360e00190a45050505061081e565b60006020835110156103f7576103f0836104bc565b9050610408565b8161040284826106db565b5060ff90505b92915050565b6000806101e0516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161044991815260200190565b602060405180830381865afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a9190610799565b9050826001600160a01b0382166104b55760405163218f5add60e11b815260040161012391906107e7565b5092915050565b600080829050601f815111156104e7578260405163305a27a960e01b815260040161012391906107e7565b80516104f2826107fa565b179392505050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561052b578181015183820152602001610513565b50506000910152565b600082601f83011261054557600080fd5b81516001600160401b0381111561055e5761055e6104fa565b604051601f8201601f19908116603f011681016001600160401b038111828210171561058c5761058c6104fa565b6040528181528382016020018510156105a457600080fd5b6105b5826020830160208701610510565b949350505050565b80516001600160a01b03811681146105d457600080fd5b919050565b6000806000606084860312156105ee57600080fd5b83516001600160401b0381111561060457600080fd5b61061086828701610534565b602086015190945090506001600160401b0381111561062e57600080fd5b61063a86828701610534565b925050610649604085016105bd565b90509250925092565b600181811c9082168061066657607f821691505b60208210810361068657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156106d657806000526020600020601f840160051c810160208510156106b35750805b601f840160051c820191505b818110156106d357600081556001016106bf565b50505b505050565b81516001600160401b038111156106f4576106f46104fa565b610708816107028454610652565b8461068c565b6020601f82116001811461073c57600083156107245750848201515b600019600385901b1c1916600184901b1784556106d3565b600084815260208120601f198516915b8281101561076c578785015182556020948501946001909201910161074c565b508482101561078a5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6000602082840312156107ab57600080fd5b6107b4826105bd565b9392505050565b600081518084526107d3816020860160208601610510565b601f01601f19169290920160200192915050565b6020815260006107b460208301846107bb565b805160208083015191908110156106865760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516110e36108cb600039600050506000505060005050600050506000505060005050600061024f0152600050506000505060005050600061049201526000610460015260006108940152600061086c015260006107c7015260006107f10152600061081b01526110e36000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631ef518f21461005c5780637f07d2831461008c57806384b0196e146100ad5780638821603c146100c8578063cfdb35bd146100db575b600080fd5b61006f61006a3660046109dc565b61010c565b6040516001600160a01b0390911681526020015b60405180910390f35b61009f61009a366004610b23565b610125565b604051908152602001610083565b6100b5610372565b6040516100839796959493929190610bc6565b61009f6100d6366004610c5e565b6103b8565b61009f6100e9366004610cb0565b600260209081526000938452604080852082529284528284209052825290205481565b600061011f61011a83610db8565b6103cb565b92915050565b60008060008380602001905181019061013e9190610e75565b815151919350915033906001600160a01b0381168214610189576040516347666ba360e11b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b50508151516000610199846103cb565b84516020808201516060909201516001600160a01b038087166000908152600284526040808220838716835285528082209287168252919093529091205492935090916001600160801b03909116908181808211610213576040516308e467d960e31b815260048101929092526024820152604401610180565b50600090506102228284610fb1565b9050600061023082896103f2565b905081156102f3576040516343edff4160e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906387dbfe829061028e908f908a908a9088908e908990600401610fda565b600060405180830381600087803b1580156102a857600080fd5b505af11580156102bc573d6000803e3d6000fd5b5050506001600160a01b0380891660009081526002602090815260408083208a851684528252808320938b16835292905220859055505b866001600160a01b0316866001600160a01b03168d600281111561031957610319610fc4565b604080516001600160a01b038a168152602081018790529081018590527ffadd34108e3c00b000a046b272ee080bb1755b91078c0ef5200c0b7da6132bd19060600160405180910390a4509a9950505050505050505050565b600060608060008060006060610386610459565b61038e61048b565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b600061011f6103c68361102e565b6104b8565b6000806103db83600001516104b8565b90506103eb81846020015161056f565b9392505050565b600061040183620f4240101590565b80610414575061041482620f4240101590565b8383909161043e5760405163768bf0eb60e11b815260048101929092526024820152604401610180565b50620f4240905061044f838561103a565b6103eb9190611051565b60606104867f00000000000000000000000000000000000000000000000000000000000000006000610599565b905090565b60606104867f00000000000000000000000000000000000000000000000000000000000000006001610599565b600061011f7fe502a96d6aaed328ceacc76a5f627b9823162f5a205dab5a702b40073a6778428360000151846020015185604001518660600151876080015180519060200120604051602001610554969594939291909586526001600160a01b0394851660208701529290931660408501526001600160401b031660608401526001600160801b0391909116608083015260a082015260c00190565b60405160208183030381529060405280519060200120610644565b60008060008061057f8686610671565b92509250925061058f82826106be565b5090949350505050565b606060ff83146105b3576105ac8361077b565b905061011f565b8180546105bf90611073565b80601f01602080910402602001604051908101604052809291908181526020018280546105eb90611073565b80156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b5050505050905061011f565b600061011f6106516107ba565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600083516041036106ab5760208401516040850151606086015160001a61069d888285856108e5565b9550955095505050506106b7565b50508151600091506002905b9250925092565b60008260038111156106d2576106d2610fc4565b036106db575050565b60018260038111156106ef576106ef610fc4565b0361070d5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561072157610721610fc4565b036107425760405163fce698f760e01b815260048101829052602401610180565b600382600381111561075657610756610fc4565b03610777576040516335e2f38360e21b815260048101829052602401610180565b5050565b60606000610788836109b4565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561081357507f000000000000000000000000000000000000000000000000000000000000000046145b1561083d57507f000000000000000000000000000000000000000000000000000000000000000090565b610486604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561092057506000915060039050826109aa565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610974573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109a0575060009250600191508290506109aa565b9250600091508190505b9450945094915050565b600060ff8216601f81111561011f57604051632cd44ac360e21b815260040160405180910390fd5b6000602082840312156109ee57600080fd5b81356001600160401b03811115610a0457600080fd5b8201604081850312156103eb57600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610a4e57610a4e610a16565b60405290565b604080519081016001600160401b0381118282101715610a4e57610a4e610a16565b604051601f8201601f191681016001600160401b0381118282101715610a9e57610a9e610a16565b604052919050565b60006001600160401b03821115610abf57610abf610a16565b50601f01601f191660200190565b600082601f830112610ade57600080fd5b8135610af1610aec82610aa6565b610a76565b818152846020838601011115610b0657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215610b3657600080fd5b823560038110610b4557600080fd5b915060208301356001600160401b03811115610b6057600080fd5b610b6c85828601610acd565b9150509250929050565b60005b83811015610b91578181015183820152602001610b79565b50506000910152565b60008151808452610bb2816020860160208601610b76565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e060208201526000610be560e0830189610b9a565b8281036040840152610bf78189610b9a565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b81811015610c4d578351835260209384019390920191600101610c2f565b50909b9a5050505050505050505050565b600060208284031215610c7057600080fd5b81356001600160401b03811115610c8657600080fd5b820160a081850312156103eb57600080fd5b6001600160a01b0381168114610cad57600080fd5b50565b600080600060608486031215610cc557600080fd5b8335610cd081610c98565b92506020840135610ce081610c98565b91506040840135610cf081610c98565b809150509250925092565b6001600160401b0381168114610cad57600080fd5b6001600160801b0381168114610cad57600080fd5b600060a08284031215610d3757600080fd5b610d3f610a2c565b90508135610d4c81610c98565b81526020820135610d5c81610c98565b60208201526040820135610d6f81610cfb565b60408201526060820135610d8281610d10565b606082015260808201356001600160401b03811115610da057600080fd5b610dac84828501610acd565b60808301525092915050565b600060408236031215610dca57600080fd5b610dd2610a54565b82356001600160401b03811115610de857600080fd5b610df436828601610d25565b82525060208301356001600160401b03811115610e1057600080fd5b610e1c36828601610acd565b60208301525092915050565b600082601f830112610e3957600080fd5b8151610e47610aec82610aa6565b818152846020838601011115610e5c57600080fd5b610e6d826020830160208701610b76565b949350505050565b60008060408385031215610e8857600080fd5b82516001600160401b03811115610e9e57600080fd5b830160408186031215610eb057600080fd5b610eb8610a54565b81516001600160401b03811115610ece57600080fd5b820160a08188031215610ee057600080fd5b610ee8610a2c565b8151610ef381610c98565b81526020820151610f0381610c98565b60208201526040820151610f1681610cfb565b60408201526060820151610f2981610d10565b606082015260808201516001600160401b03811115610f4757600080fd5b610f5389828501610e28565b60808301525082525060208201516001600160401b03811115610f7557600080fd5b610f8187828501610e28565b602083810191909152959095015190969095509350505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011f5761011f610f9b565b634e487b7160e01b600052602160045260246000fd5b60c0810160038810610ffc57634e487b7160e01b600052602160045260246000fd5b9681526001600160a01b03958616602082015293851660408501526060840192909252909216608082015260a0015290565b600061011f3683610d25565b808202811582820484141761011f5761011f610f9b565b60008261106e57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061108757607f821691505b6020821081036110a757634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212204ea11b7f590e7303a0b1850b4cd59148c357bb48498bdb2606c6e97c057012e264736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80631ef518f21461005c5780637f07d2831461008c57806384b0196e146100ad5780638821603c146100c8578063cfdb35bd146100db575b600080fd5b61006f61006a3660046109dc565b61010c565b6040516001600160a01b0390911681526020015b60405180910390f35b61009f61009a366004610b23565b610125565b604051908152602001610083565b6100b5610372565b6040516100839796959493929190610bc6565b61009f6100d6366004610c5e565b6103b8565b61009f6100e9366004610cb0565b600260209081526000938452604080852082529284528284209052825290205481565b600061011f61011a83610db8565b6103cb565b92915050565b60008060008380602001905181019061013e9190610e75565b815151919350915033906001600160a01b0381168214610189576040516347666ba360e11b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b50508151516000610199846103cb565b84516020808201516060909201516001600160a01b038087166000908152600284526040808220838716835285528082209287168252919093529091205492935090916001600160801b03909116908181808211610213576040516308e467d960e31b815260048101929092526024820152604401610180565b50600090506102228284610fb1565b9050600061023082896103f2565b905081156102f3576040516343edff4160e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906387dbfe829061028e908f908a908a9088908e908990600401610fda565b600060405180830381600087803b1580156102a857600080fd5b505af11580156102bc573d6000803e3d6000fd5b5050506001600160a01b0380891660009081526002602090815260408083208a851684528252808320938b16835292905220859055505b866001600160a01b0316866001600160a01b03168d600281111561031957610319610fc4565b604080516001600160a01b038a168152602081018790529081018590527ffadd34108e3c00b000a046b272ee080bb1755b91078c0ef5200c0b7da6132bd19060600160405180910390a4509a9950505050505050505050565b600060608060008060006060610386610459565b61038e61048b565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b600061011f6103c68361102e565b6104b8565b6000806103db83600001516104b8565b90506103eb81846020015161056f565b9392505050565b600061040183620f4240101590565b80610414575061041482620f4240101590565b8383909161043e5760405163768bf0eb60e11b815260048101929092526024820152604401610180565b50620f4240905061044f838561103a565b6103eb9190611051565b60606104867f00000000000000000000000000000000000000000000000000000000000000006000610599565b905090565b60606104867f00000000000000000000000000000000000000000000000000000000000000006001610599565b600061011f7fe502a96d6aaed328ceacc76a5f627b9823162f5a205dab5a702b40073a6778428360000151846020015185604001518660600151876080015180519060200120604051602001610554969594939291909586526001600160a01b0394851660208701529290931660408501526001600160401b031660608401526001600160801b0391909116608083015260a082015260c00190565b60405160208183030381529060405280519060200120610644565b60008060008061057f8686610671565b92509250925061058f82826106be565b5090949350505050565b606060ff83146105b3576105ac8361077b565b905061011f565b8180546105bf90611073565b80601f01602080910402602001604051908101604052809291908181526020018280546105eb90611073565b80156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b5050505050905061011f565b600061011f6106516107ba565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600083516041036106ab5760208401516040850151606086015160001a61069d888285856108e5565b9550955095505050506106b7565b50508151600091506002905b9250925092565b60008260038111156106d2576106d2610fc4565b036106db575050565b60018260038111156106ef576106ef610fc4565b0361070d5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561072157610721610fc4565b036107425760405163fce698f760e01b815260048101829052602401610180565b600382600381111561075657610756610fc4565b03610777576040516335e2f38360e21b815260048101829052602401610180565b5050565b60606000610788836109b4565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561081357507f000000000000000000000000000000000000000000000000000000000000000046145b1561083d57507f000000000000000000000000000000000000000000000000000000000000000090565b610486604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561092057506000915060039050826109aa565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610974573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109a0575060009250600191508290506109aa565b9250600091508190505b9450945094915050565b600060ff8216601f81111561011f57604051632cd44ac360e21b815260040160405180910390fd5b6000602082840312156109ee57600080fd5b81356001600160401b03811115610a0457600080fd5b8201604081850312156103eb57600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610a4e57610a4e610a16565b60405290565b604080519081016001600160401b0381118282101715610a4e57610a4e610a16565b604051601f8201601f191681016001600160401b0381118282101715610a9e57610a9e610a16565b604052919050565b60006001600160401b03821115610abf57610abf610a16565b50601f01601f191660200190565b600082601f830112610ade57600080fd5b8135610af1610aec82610aa6565b610a76565b818152846020838601011115610b0657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215610b3657600080fd5b823560038110610b4557600080fd5b915060208301356001600160401b03811115610b6057600080fd5b610b6c85828601610acd565b9150509250929050565b60005b83811015610b91578181015183820152602001610b79565b50506000910152565b60008151808452610bb2816020860160208601610b76565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e060208201526000610be560e0830189610b9a565b8281036040840152610bf78189610b9a565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b81811015610c4d578351835260209384019390920191600101610c2f565b50909b9a5050505050505050505050565b600060208284031215610c7057600080fd5b81356001600160401b03811115610c8657600080fd5b820160a081850312156103eb57600080fd5b6001600160a01b0381168114610cad57600080fd5b50565b600080600060608486031215610cc557600080fd5b8335610cd081610c98565b92506020840135610ce081610c98565b91506040840135610cf081610c98565b809150509250925092565b6001600160401b0381168114610cad57600080fd5b6001600160801b0381168114610cad57600080fd5b600060a08284031215610d3757600080fd5b610d3f610a2c565b90508135610d4c81610c98565b81526020820135610d5c81610c98565b60208201526040820135610d6f81610cfb565b60408201526060820135610d8281610d10565b606082015260808201356001600160401b03811115610da057600080fd5b610dac84828501610acd565b60808301525092915050565b600060408236031215610dca57600080fd5b610dd2610a54565b82356001600160401b03811115610de857600080fd5b610df436828601610d25565b82525060208301356001600160401b03811115610e1057600080fd5b610e1c36828601610acd565b60208301525092915050565b600082601f830112610e3957600080fd5b8151610e47610aec82610aa6565b818152846020838601011115610e5c57600080fd5b610e6d826020830160208701610b76565b949350505050565b60008060408385031215610e8857600080fd5b82516001600160401b03811115610e9e57600080fd5b830160408186031215610eb057600080fd5b610eb8610a54565b81516001600160401b03811115610ece57600080fd5b820160a08188031215610ee057600080fd5b610ee8610a2c565b8151610ef381610c98565b81526020820151610f0381610c98565b60208201526040820151610f1681610cfb565b60408201526060820151610f2981610d10565b606082015260808201516001600160401b03811115610f4757600080fd5b610f5389828501610e28565b60808301525082525060208201516001600160401b03811115610f7557600080fd5b610f8187828501610e28565b602083810191909152959095015190969095509350505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011f5761011f610f9b565b634e487b7160e01b600052602160045260246000fd5b60c0810160038810610ffc57634e487b7160e01b600052602160045260246000fd5b9681526001600160a01b03958616602082015293851660408501526060840192909252909216608082015260a0015290565b600061011f3683610d25565b808202811582820484141761011f5761011f610f9b565b60008261106e57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061108757607f821691505b6020821081036110a757634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212204ea11b7f590e7303a0b1850b4cd59148c357bb48498bdb2606c6e97c057012e264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-11155111/deployed_addresses.json b/packages/horizon/ignition/deployments/chain-11155111/deployed_addresses.json new file mode 100644 index 000000000..07d87c022 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/deployed_addresses.json @@ -0,0 +1,41 @@ +{ + "BridgeEscrow#BridgeEscrow": "0xD1e69Dd541597F3a976ec34416F806322C560509", + "Controller#Controller": "0x9746Fb649B0AD9BA77201e9bf4e864B852e60841", + "HorizonProxies#OZProxyDummy_GraphPayments": "0x2366Bb0Ce360465153e0fF2945A14e820E6a1A14", + "Curation#Curation": "0xB20db0C5b472A25913f668bdAeE299880F3761e5", + "Curation#GraphCurationToken": "0x85820DB0AbC0f869fF5B8C47d80baD8ce8D23e36", + "EpochManager#EpochManager": "0xaBDda0b824b1581Ad6bE147AE5ED7E42B8D90602", + "GraphProxyAdmin#GraphProxyAdmin": "0x86e0221dBe437a67120BdBB8c53847Fb4D756416", + "GraphToken#GraphToken": "0xFBdc2dEbD9d3C57c5A61c958edcaA8C3a54c6188", + "GraphTokenGateway#GraphTokenGateway": "0x2e2a734Aad8Ff4B60E88b211B0daC398eCC2098c", + "HorizonProxies#OZProxyDummy_PaymentsEscrow": "0xC1Ce222a5A5f0e4CA5beF19cF6f53714288b9FFA", + "HorizonStakingExtension#ExponentialRebates": "0xA018c2419084c2DfC9C321103c2D5a98d4Db137c", + "RewardsManager#RewardsManager": "0x1c37C0725527C76B9B48DaFcE78673bB7354B3a1", + "HorizonProxies#TransparentUpgradeableProxy_GraphPayments": "0x5C72b84F619399087Df1e4b686050A5F336126D9", + "HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow": "0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53", + "BridgeEscrow#GraphProxy": "0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F", + "Curation#GraphProxy": "0xEC2ed45a73BD2A324739691eaf425aDD66918FAb", + "EpochManager#GraphProxy": "0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA", + "GraphToken#GraphProxy": "0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205", + "GraphTokenGateway#GraphProxy": "0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51", + "RewardsManager#GraphProxy": "0xCab63af715010d12dA2128777abB2103F9a0EF8F", + "BridgeEscrow#BridgeEscrow_Instance": "0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F", + "Curation#Curation_Instance": "0xEC2ed45a73BD2A324739691eaf425aDD66918FAb", + "EpochManager#EpochManager_Instance": "0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA", + "GraphToken#GraphToken_Instance": "0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205", + "GraphTokenGateway#GraphTokenGateway_Instance": "0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51", + "HorizonProxies#ProxyAdmin_GraphPayments": "0xaBE1e45c636a27aD02f0022e0AB32BF350702Df1", + "HorizonProxies#ProxyAdmin_PaymentsEscrow": "0x9fa225C2D4Cf40c8B0100Af7dacb8bCf84D822d0", + "RewardsManager#RewardsManager_Instance": "0xCab63af715010d12dA2128777abB2103F9a0EF8F", + "GraphHorizon_Periphery#Dummy": "0x31a62E69D8A4003365A97758091685eA72333155", + "HorizonProxies#GraphProxy_HorizonStaking": "0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2", + "HorizonProxies#RegisteredDummy": "0x73bb9ee763C815ae288f5c75187cb3Be2De1DA38", + "GraphPayments#GraphPayments_Instance": "0x5C72b84F619399087Df1e4b686050A5F336126D9", + "PaymentsEscrow#PaymentsEscrow_Instance": "0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53", + "GraphPayments#GraphPayments": "0x0E0e9AC171562b6d6141f69075DEd1E3922930B7", + "HorizonStakingExtension#HorizonStakingExtension": "0xeB436D1CF0d6EabC759EB3bCd96BdBA4cD208eb3", + "PaymentsEscrow#PaymentsEscrow": "0x834f7Fd38818dF6d79265e0BBb56A06168356231", + "TAPCollector#TAPCollector": "0xfd24C169Cb89c448aaeB570507aAF77ff9277E4f", + "HorizonStaking#HorizonStaking": "0x4C6301489267EA82BeDA87d4dabc50A210aBa275", + "HorizonStaking#HorizonStaking_Instance": "0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2" +} diff --git a/packages/horizon/ignition/deployments/chain-11155111/journal.jsonl b/packages/horizon/ignition/deployments/chain-11155111/journal.jsonl new file mode 100644 index 000000000..f2c983d93 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-11155111/journal.jsonl @@ -0,0 +1,318 @@ + +{"chainId":11155111,"type":"DEPLOYMENT_INITIALIZE"} +{"artifactId":"BridgeEscrow#BridgeEscrow","constructorArgs":[],"contractName":"BridgeEscrow","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"BridgeEscrow#BridgeEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"BridgeEscrow#BridgeEscrow","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051610c376101696000398061071f5250806106f65250806106cd528061089e5250806106a452508061067b5250806106525250806106295250610c376000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"BridgeEscrow#BridgeEscrow","networkInteractionId":1,"nonce":235,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x1e244f483b0bae4940372bac6ff73138a3cbe8eb8b8ea82667f56e2e5250afd3"},"type":"TRANSACTION_SEND"} +{"artifactId":"Controller#Controller","constructorArgs":[],"contractName":"Controller","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"Controller#Controller","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Controller#Controller","networkInteraction":{"data":"0x608060405234801561001057600080fd5b506100243361003360201b6109b21760201c565b61002e6001610055565b6100e7565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff1615158115151415610075576100e4565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff910416156100a157426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a15b50565b610ba0806100f66000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80636cda3798116100a2578063e0e9929211610071578063e0e9929214610215578063e3056a3414610241578063eb5dd94f14610249578063f2fde38b14610275578063f7641a5e1461029b5761010b565b80636cda3798146101ce57806379ba5097146101e85780639181df9c146101f057806391b4ded91461020d5761010b565b806348bde20c116100de57806348bde20c146101795780634fc07d751461019f57806356371bd8146101a75780635c975abb146101c65761010b565b80630c340a241461011057806316c38b3c1461013457806324a3d622146101555780632e292fc71461015d575b600080fd5b6101186102b8565b604080516001600160a01b039092168252519081900360200190f35b6101536004803603602081101561014a57600080fd5b503515156102c7565b005b610118610331565b610165610340565b604080519115158252519081900360200190f35b6101536004803603602081101561018f57600080fd5b50356001600160a01b0316610350565b61011861040c565b610153600480360360208110156101bd57600080fd5b5035151561041b565b610165610482565b6101d6610492565b60408051918252519081900360200190f35b610153610498565b6101536004803603602081101561020657600080fd5b50356105a6565b6101d6610651565b6101536004803603604081101561022b57600080fd5b50803590602001356001600160a01b0316610657565b61011861076e565b6101536004803603604081101561025f57600080fd5b50803590602001356001600160a01b031661077d565b6101536004803603602081101561028b57600080fd5b50356001600160a01b0316610899565b610118600480360360208110156102b157600080fd5b5035610997565b6000546001600160a01b031681565b6000546001600160a01b03163314806102ea57506004546001600160a01b031633145b6103255760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e816109d4565b50565b6004546001600160a01b031681565b600154600160a01b900460ff1690565b6000546001600160a01b031633146103a8576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610403576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b61032e81610a65565b6000546001600160a01b031690565b6000546001600160a01b031633148061043e57506004546001600160a01b031633145b6104795760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e81610ab7565b600154600160a81b900460ff1690565b60025481565b6001546001600160a01b031680158015906104bb5750336001600160a01b038216145b61050c576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b031916905580519283525183927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a250565b60035481565b6000546001600160a01b031633146106af576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661070a576040805162461bcd60e51b815260206004820152601c60248201527f436f6e74726163742061646472657373206d7573742062652073657400000000604482015290519081900360640190fd5b60008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a25050565b6001546001600160a01b031681565b6000546001600160a01b031633146107d5576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610829576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b6000828152600560205260408082205481516392eefe9b60e01b81526001600160a01b038581166004830152925192909116926392eefe9b9260248084019382900301818387803b15801561087d57600080fd5b505af1158015610891573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146108f1576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610943576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000908152600560205260409020546001600160a01b031690565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff16151581151514156109f45761032e565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615610a2057426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b600160149054906101000a900460ff1615158115151415610ad75761032e565b6001805460ff60a01b1916600160a01b8315158102919091179182905560ff91041615610b0357426002555b60015460408051600160a01b90920460ff1615158252517f511b770d1b1dc5cbd412a5017f55cbb2295b826385e5f46c1de2b6ebeb44ae02916020908290030190a15056fe4f6e6c7920476f7665726e6f72206f7220477561726469616e2063616e2063616c6ca2646970667358221220c742dbbf8f38fda928d26053c584788bb7d7b003131594b9e14f1381ebbdbb3064736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Controller#Controller","networkInteractionId":1,"nonce":236,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x8b933f38a21564afa1108579355a9b9425641c9a7a23948ab68b552486f14583"},"type":"TRANSACTION_SEND"} +{"artifactId":"Curation#Curation","constructorArgs":[],"contractName":"Curation","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"Curation#Curation","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#Curation","networkInteraction":{"data":"0x6101806040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea361014052613d0960e61b6101605234801561011a57600080fd5b5060805160a05160c05160e0516101005161012051610140516101605160e01c6128cc61018f60003980610c2f52508061141b52806119025250806113f25250806113c9528061180c5250806113a05280611dbf5250806113775280611ff252508061134e52508061132552506128cc6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#Curation","networkInteractionId":1,"nonce":237,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xf48f23e53e8adc84dd2731b1223dbfc7a88aa1554a050dd886e4f32bf4b47252"},"type":"TRANSACTION_SEND"} +{"artifactId":"Curation#GraphCurationToken","constructorArgs":[],"contractName":"GraphCurationToken","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"Curation#GraphCurationToken","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#GraphCurationToken","networkInteraction":{"data":"0x608060405234801561001057600080fd5b506114ec806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806379ba5097116100a2578063a9059cbb11610071578063a9059cbb14610352578063c4d66de81461037e578063dd62ed3e146103a4578063e3056a34146103d2578063f2fde38b146103da57610116565b806379ba5097146102ea57806379cc6790146102f257806395d89b411461031e578063a457c2d71461032657610116565b806323b872dd116100e957806323b872dd14610216578063313ce5671461024c578063395093511461026a57806340c10f191461029657806370a08231146102c457610116565b806306fdde031461011b578063095ea7b3146101985780630c340a24146101d857806318160ddd146101fc575b600080fd5b610123610400565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015d578181015183820152602001610145565b50505050905090810190601f16801561018a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c4600480360360408110156101ae57600080fd5b506001600160a01b038135169060200135610496565b604080519115158252519081900360200190f35b6101e06104b3565b604080516001600160a01b039092168252519081900360200190f35b6102046104c2565b60408051918252519081900360200190f35b6101c46004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356104c8565b61025461054f565b6040805160ff9092168252519081900360200190f35b6101c46004803603604081101561028057600080fd5b506001600160a01b038135169060200135610558565b6102c2600480360360408110156102ac57600080fd5b506001600160a01b0381351690602001356105a6565b005b610204600480360360208110156102da57600080fd5b50356001600160a01b031661060c565b6102c2610627565b6102c26004803603604081101561030857600080fd5b506001600160a01b038135169060200135610737565b610123610799565b6101c46004803603604081101561033c57600080fd5b506001600160a01b0381351690602001356107fa565b6101c46004803603604081101561036857600080fd5b506001600160a01b038135169060200135610862565b6102c26004803603602081101561039457600080fd5b50356001600160a01b0316610876565b610204600480360360408110156103ba57600080fd5b506001600160a01b0381358116916020013516610972565b6101e061099d565b6102c2600480360360208110156103f057600080fd5b50356001600160a01b03166109ac565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b820191906000526020600020905b81548152906001019060200180831161046f57829003601f168201915b5050505050905090565b60006104aa6104a3610aaa565b8484610aae565b50600192915050565b6065546001600160a01b031681565b60355490565b60006104d5848484610b9a565b610545846104e1610aaa565b61054085604051806060016040528060288152602001611400602891396001600160a01b038a1660009081526034602052604081209061051f610aaa565b6001600160a01b031681526020810191909152604001600020549190610cf7565b610aae565b5060019392505050565b60385460ff1690565b60006104aa610565610aaa565b846105408560346000610576610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610d8e565b6065546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610def565b5050565b6001600160a01b031660009081526033602052604090205490565b6066546001600160a01b0316801580159061064a5750336001600160a01b038216145b61069b576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b606580546001600160a01b038381166001600160a01b0319808416919091179384905560668054909116905560405191811692169082907f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f90600090a36066546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6065546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610ee1565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b60006104aa610807610aaa565b84610540856040518060600160405280602581526020016114926025913960346000610831610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610cf7565b60006104aa61086f610aaa565b8484610b9a565b600054610100900460ff168061088f575061088f610fdd565b8061089d575060005460ff16155b6108d85760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015610903576000805460ff1961ff0019909116610100171660011790555b61090c82610fee565b61095d604051806040016040528060148152602001734772617068204375726174696f6e20536861726560601b8152506040518060400160405280600381526020016247435360e81b815250611010565b8015610608576000805461ff00191690555050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6066546001600160a01b031681565b6065546001600160a01b03163314610a04576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610a56576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b606680546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b038316610af35760405162461bcd60e51b815260040180806020018281038252602481526020018061146e6024913960400191505060405180910390fd5b6001600160a01b038216610b385760405162461bcd60e51b815260040180806020018281038252602281526020018061138a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610bdf5760405162461bcd60e51b81526004018080602001828103825260258152602001806114496025913960400191505060405180910390fd5b6001600160a01b038216610c245760405162461bcd60e51b81526004018080602001828103825260238152602001806113456023913960400191505060405180910390fd5b610c2f8383836110c1565b610c6c816040518060600160405280602681526020016113ac602691396001600160a01b0386166000908152603360205260409020549190610cf7565b6001600160a01b038085166000908152603360205260408082209390935590841681522054610c9b9082610d8e565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610d865760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d4b578181015183820152602001610d33565b50505050905090810190601f168015610d785780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610de8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610e4a576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610e56600083836110c1565b603554610e639082610d8e565b6035556001600160a01b038216600090815260336020526040902054610e899082610d8e565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610f265760405162461bcd60e51b81526004018080602001828103825260218152602001806114286021913960400191505060405180910390fd5b610f32826000836110c1565b610f6f81604051806060016040528060228152602001611368602291396001600160a01b0385166000908152603360205260409020549190610cf7565b6001600160a01b038316600090815260336020526040902055603554610f9590826110c6565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000610fe830611123565b15905090565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16806110295750611029610fdd565b80611037575060005460ff16155b6110725760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff1615801561109d576000805460ff1961ff0019909116610100171660011790555b6110a5611129565b6110af83836111cb565b80156110c1576000805461ff00191690555b505050565b60008282111561111d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600054610100900460ff16806111425750611142610fdd565b80611150575060005460ff16155b61118b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff161580156111b6576000805460ff1961ff0019909116610100171660011790555b80156111c8576000805461ff00191690555b50565b600054610100900460ff16806111e457506111e4610fdd565b806111f2575060005460ff16155b61122d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015611258576000805460ff1961ff0019909116610100171660011790555b825161126b9060369060208601906112a3565b50815161127f9060379060208501906112a3565b506038805460ff1916601217905580156110c1576000805461ff0019169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826112d9576000855561131f565b82601f106112f257805160ff191683800117855561131f565b8280016001018555821561131f579182015b8281111561131f578251825591602001919060010190611304565b5061132b92915061132f565b5090565b5b8082111561132b576000815560010161133056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200b687fddcd01dbad6e1d5fbd49cb041f69ed61684a12a4c26c6e37e0f5ad7c2a64736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#GraphCurationToken","networkInteractionId":1,"nonce":238,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x42bb5c8a740352fe4ed4296d836ffac44d431f8f2ef3caef87a04f6b73c3a83b"},"type":"TRANSACTION_SEND"} +{"artifactId":"EpochManager#EpochManager","constructorArgs":[],"contractName":"EpochManager","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"EpochManager#EpochManager","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"EpochManager#EpochManager","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161103461016460003980610aac525080610a83525080610a5a525080610a31525080610a085250806109df5250806109b652506110346000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"EpochManager#EpochManager","networkInteractionId":1,"nonce":239,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x9cc51e406b48c153b346fcdd834ff65d3167ce1df8dd5596a07f02e139b92f77"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphProxyAdmin#GraphProxyAdmin","constructorArgs":[],"contractName":"GraphProxyAdmin","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"GraphProxyAdmin#GraphProxyAdmin","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","networkInteraction":{"data":"0x608060405234801561001057600080fd5b506100243361002960201b610a0c1760201c565b61004b565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610a648061005a6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80637eff275e116100715780637eff275e146101b157806399a88ec4146101df578063e3056a341461020d578063eb451a0214610215578063f2fde38b14610243578063f3b7dead14610269576100a9565b806307ebde0e146100ae5780630c340a2414610139578063204e1c7a1461015d5780635bf410eb1461018357806379ba5097146101a9575b600080fd5b610137600480360360608110156100c457600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b50909250905061028f565b005b610141610388565b604080516001600160a01b039092168252519081900360200190f35b6101416004803603602081101561017357600080fd5b50356001600160a01b0316610397565b6101416004803603602081101561019957600080fd5b50356001600160a01b031661046a565b610137610525565b610137600480360360408110156101c757600080fd5b506001600160a01b0381358116916020013516610633565b610137600480360360408110156101f557600080fd5b506001600160a01b03813581169160200135166106f6565b61014161079d565b6101376004803603604081101561022b57600080fd5b506001600160a01b03813581169160200135166107ac565b6101376004803603602081101561025957600080fd5b50356001600160a01b0316610853565b6101416004803603602081101561027f57600080fd5b50356001600160a01b0316610951565b6000546001600160a01b031633146102e7576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b836001600160a01b0316639ce7abe58484846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b15801561036a57600080fd5b505af115801561037e573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031681565b6000806000836001600160a01b03166040518080635c60da1b60e01b8152506004019050600060405180830381855afa9150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b50915091508161044b576040805162461bcd60e51b8152602060048201526016602482015275141c9bde1e481a5b5c1b0818d85b1b0819985a5b195960521b604482015290519081900360640190fd5b80806020019051602081101561046057600080fd5b5051949350505050565b6000806000836001600160a01b0316604051808063396f7b2360e01b8152506004019050600060405180830381855afa9150503d80600081146104c9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ce565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601d60248201527f50726f78792070656e64696e67496d706c2063616c6c206661696c6564000000604482015290519081900360640190fd5b6001546001600160a01b031680158015906105485750336001600160a01b038216145b610599576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b0316331461068b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663704b6c02826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b505af11580156106ee573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461074e576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b0316633659cfe6826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6001546001600160a01b031681565b6000546001600160a01b03163314610804576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663a2594d82826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6000546001600160a01b031633146108ab576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b0381166108fd576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000806000836001600160a01b031660405180806303e1469160e61b8152506004019050600060405180830381855afa9150503d80600081146109b0576040519150601f19603f3d011682016040523d82523d6000602084013e6109b5565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601760248201527f50726f78792061646d696e2063616c6c206661696c6564000000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b039290921691909117905556fea26469706673582212208b271ee4c7625d89f662c15e90f70e142245bf56f0595043fe9af742b09d958c64736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","networkInteractionId":1,"nonce":240,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x245dbac23a75574bbf072a23c55ece60c19fc4928f874704661c7770d4aaf676"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphToken#GraphToken","constructorArgs":[],"contractName":"GraphToken","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"GraphToken#GraphToken","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken","networkInteraction":{"data":"0x6101206040527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726080527fefcec85968da792893fa503eb21730083fc6c50ed5461e56163b28335b2a5f9660a0527f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d60c0527fe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f565959160e0527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610100523480156100c657600080fd5b5060805160a05160c05160e0516101005161261e61010660003980611547525080611eae525080611e5e525080611e3d525080611e1c525061261e6000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken","networkInteractionId":1,"nonce":241,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x0a085a815d30e599f281fbde7a0df8a8a9ee5090481a33ffc226166bbdf6061e"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphTokenGateway#GraphTokenGateway","constructorArgs":[],"contractName":"GraphTokenGateway","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"GraphTokenGateway#GraphTokenGateway","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphTokenGateway","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161222b6101696000398061112f5250806111065250806110dd528061150a5250806110b452508061108b525080611062525080611039525061222b6000f3fe6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphTokenGateway","networkInteractionId":1,"nonce":242,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8613258860"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x4e38b4bf3a9619551af22cef109c26563a6dc71930e8a27277af36515e66e969"},"type":"TRANSACTION_SEND"} +{"artifactId":"HorizonProxies#OZProxyDummy_GraphPayments","constructorArgs":[],"contractName":"Dummy","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonProxies#OZProxyDummy_GraphPayments","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","networkInteractionId":1,"nonce":243,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8120140386"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x45a22a889928909c7dc20797225a885e24022bde79231ad84387574afae8303d"},"type":"TRANSACTION_SEND"} +{"artifactId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","constructorArgs":[],"contractName":"Dummy","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","networkInteractionId":1,"nonce":244,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8120140386"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xd25cc7260b9f404196709c9bfd8222de1ca28626fa44050d22983038e053de6e"},"type":"TRANSACTION_SEND"} +{"artifactId":"HorizonStakingExtension#ExponentialRebates","constructorArgs":[],"contractName":"ExponentialRebates","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonStakingExtension#ExponentialRebates","futureType":"LIBRARY_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStakingExtension#ExponentialRebates","networkInteraction":{"data":"0x610c2d610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c806349484d811461003a575b600080fd5b61004d610048366004610a66565b61005f565b60405190815260200160405180910390f35b6000806100728660030b8660030b61011c565b9050806000036100855787915050610112565b87600003610097576000915050610112565b60006100a98560030b8560030b61011c565b905060006100b8828a8c61013c565b9050600f6100c582610153565b13156100d657899350505050610112565b60006100ff6001607f1b6100fa866100f56100f087610ae2565b610169565b610882565b61089d565b905061010b818c6108d4565b9450505050505b9695505050505050565b600061013561012f846001607f1b610920565b83610988565b9392505050565b600061014b61012f8585610920565b949350505050565b60006101636001607f1b83610b14565b92915050565b60006101796101ff607c1b610ae2565b82121561018857506000919050565b8160000361019b57506001607f1b919050565b60008213156101c55760405162461bcd60e51b81526004016101bc90610b42565b60405180910390fd5b6000806101d66001607c1b85610b69565b91508190506001607f1b6101ea8280610b7d565b6101f49190610b14565b9050610208816710e1b3be415a0000610b7d565b6102129084610bad565b92506001607f1b6102238383610b7d565b61022d9190610b14565b9050610241816705a0913f6b1e0000610b7d565b61024b9084610bad565b92506001607f1b61025c8383610b7d565b6102669190610b14565b905061027a81670168244fdac78000610b7d565b6102849084610bad565b92506001607f1b6102958383610b7d565b61029f9190610b14565b90506102b281664807432bc18000610b7d565b6102bc9084610bad565b92506001607f1b6102cd8383610b7d565b6102d79190610b14565b90506102ea81660c0135dca04000610b7d565b6102f49084610bad565b92506001607f1b6103058383610b7d565b61030f9190610b14565b9050610322816601b707b1cdc000610b7d565b61032c9084610bad565b92506001607f1b61033d8383610b7d565b6103479190610b14565b9050610359816536e0f639b800610b7d565b6103639084610bad565b92506001607f1b6103748383610b7d565b61037e9190610b14565b905061039081650618fee9f800610b7d565b61039a9084610bad565b92506001607f1b6103ab8383610b7d565b6103b59190610b14565b90506103c681649c197dcc00610b7d565b6103d09084610bad565b92506001607f1b6103e18383610b7d565b6103eb9190610b14565b90506103fc81640e30dce400610b7d565b6104069084610bad565b92506001607f1b6104178383610b7d565b6104219190610b14565b90506104328164012ebd1300610b7d565b61043c9084610bad565b92506001607f1b61044d8383610b7d565b6104579190610b14565b9050610467816317499f00610b7d565b6104719084610bad565b92506001607f1b6104828383610b7d565b61048c9190610b14565b905061049c816301a9d480610b7d565b6104a69084610bad565b92506001607f1b6104b78383610b7d565b6104c19190610b14565b90506104d081621c6380610b7d565b6104da9084610bad565b92506001607f1b6104eb8383610b7d565b6104f59190610b14565b9050610504816201c638610b7d565b61050e9084610bad565b92506001607f1b61051f8383610b7d565b6105299190610b14565b905061053781611ab8610b7d565b6105419084610bad565b92506001607f1b6105528383610b7d565b61055c9190610b14565b905061056a8161017c610b7d565b6105749084610bad565b92506001607f1b6105858383610b7d565b61058f9190610b14565b905061059c816014610b7d565b6105a69084610bad565b92506001607f1b6105b78383610b7d565b6105c19190610b14565b90506105ce816001610b7d565b6105d89084610bad565b92506001607f1b826105f26721c3677c82b4000086610b14565b6105fc9190610bad565b6106069190610bad565b925061061184610ae2565b9350600160841b841615610657577243cbaf42a000812488fc5c220ad7b97bf6e99e61064a6cf1aaddd7742e56d32fb9f9974485610b7d565b6106549190610b14565b92505b600160831b84161561069c577105d27a9f51c31b7c2f8038212a057477999161068f6e0afe10820813d65dfe6a33c07f738f85610b7d565b6106999190610b14565b92505b600160821b8416156106e157701b4c902e273a58678d6d3bfdb93db96d026106d46f02582ab704279e8efd15e0265855c47a85610b7d565b6106de9190610b14565b92505b600160811b841615610726577003b1cc971a9bb5b9867477440d6d1577506107196f1152aaa3bf81cb9fdb76eae12d02957185610b7d565b6107239190610b14565b92505b600160801b84161561076b5770015bf0a8b1457695355fb8ac404e7a79e361075e6f2f16ac6c59de6f8d5d6f63c1482a7c8685610b7d565b6107689190610b14565b92505b6001607f1b8416156107af576fd3094c70f034de4b96ff7d5b6f99fcd86107a26f4da2cbf1be5827f9eb3ad1aa9866ebb385610b7d565b6107ac9190610b14565b92505b6001607e1b8416156107f3576fa45af1e1f40c333b3de1db4dd55f29a76107e66f63afbe7ab2082ba1a0ae5e4eb1b479dc85610b7d565b6107f09190610b14565b92505b6001607d1b841615610837576f910b022db7ae67ce76b441c27035c6a161082a6f70f5a893b608861e1f58934f97aea57d85610b7d565b6108349190610b14565b92505b6001607c1b84161561087b576f88415abbe9a76bead8d00cf112e4d4a861086e6f783eafef1c0a8f3978c7f81824d62ebf85610b7d565b6108789190610b14565b92505b5050919050565b60006001607f1b6108938484610920565b6101359190610b14565b6000600160ff1b82036108c25760405162461bcd60e51b81526004016101bc90610b42565b610135836108cf84610ae2565b6109f2565b6000808212156108f65760405162461bcd60e51b81526004016101bc90610b42565b60006109028484610920565b905060008113610916576000915050610163565b607f1c9392505050565b600082158061092d575081155b1561093a57506000610163565b508181028183828161094e5761094e610afe565b0514158061096b57508282828161096757610967610afe565b0514155b156101635760405162461bcd60e51b81526004016101bc90610bd5565b6000816000036109aa5760405162461bcd60e51b81526004016101bc90610bd5565b600160ff1b831480156109be575081600019145b156109db5760405162461bcd60e51b81526004016101bc90610bd5565b8183816109ea576109ea610afe565b059392505050565b818101600083128015610a055750600082125b8015610a1057508281135b8061096b5750600083138015610a265750600082135b801561096b5750828112156101635760405162461bcd60e51b81526004016101bc90610bd5565b803563ffffffff81168114610a6157600080fd5b919050565b60008060008060008060c08789031215610a7f57600080fd5b8635955060208701359450610a9660408801610a4d565b9350610aa460608801610a4d565b9250610ab260808801610a4d565b9150610ac060a08801610a4d565b90509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201610af757610af7610acc565b5060000390565b634e487b7160e01b600052601260045260246000fd5b600082610b2357610b23610afe565b600160ff1b821460001984141615610b3d57610b3d610acc565b500590565b6020808252600d908201526c6f75742d6f662d626f756e647360981b604082015260600190565b600082610b7857610b78610afe565b500790565b80820260008212600160ff1b84141615610b9957610b99610acc565b818105831482151761016357610163610acc565b8082018281126000831280158216821582161715610bcd57610bcd610acc565b505092915050565b6020808252600890820152676f766572666c6f7760c01b60408201526060019056fea26469706673582212201cac81319f1bc19d15bc3a02519b03e3559a9cf147525a96caa8cb800f74da2864736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStakingExtension#ExponentialRebates","networkInteractionId":1,"nonce":245,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8120140386"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x648676702a8f33c1289655be95cc8131cf9a1987fccc64da8ab5b7bcfd87743e"},"type":"TRANSACTION_SEND"} +{"artifactId":"RewardsManager#RewardsManager","constructorArgs":[],"contractName":"RewardsManager","dependencies":[],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"RewardsManager#RewardsManager","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051611eb861017360003980610fe1525080610fb8525080610f8f528061194f525080610f6652806116d2525080610f3d525080610f14525080610eeb52806115165250611eb86000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager","networkInteractionId":1,"nonce":246,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"9046398448"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x9feb7887395ce34be9acdc287aa24f8bad99ddfa64dcde874322a0895769fc20"},"type":"TRANSACTION_SEND"} +{"futureId":"BridgeEscrow#BridgeEscrow","hash":"0x1e244f483b0bae4940372bac6ff73138a3cbe8eb8b8ea82667f56e2e5250afd3","networkInteractionId":1,"receipt":{"blockHash":"0x103bc987eaddc9dc5ff9838e8a9eb67527a3aef3ed085f29ff1e520c8f6af956","blockNumber":6722861,"contractAddress":"0xD1e69Dd541597F3a976ec34416F806322C560509","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"BridgeEscrow#BridgeEscrow","result":{"address":"0xD1e69Dd541597F3a976ec34416F806322C560509","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"Controller#Controller","hash":"0x8b933f38a21564afa1108579355a9b9425641c9a7a23948ab68b552486f14583","networkInteractionId":1,"receipt":{"blockHash":"0x103bc987eaddc9dc5ff9838e8a9eb67527a3aef3ed085f29ff1e520c8f6af956","blockNumber":6722861,"contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x0000000000000000000000000000000000000000000000000000000000000001","logIndex":324,"topics":["0x8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Controller#Controller","result":{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","hash":"0x45a22a889928909c7dc20797225a885e24022bde79231ad84387574afae8303d","networkInteractionId":1,"receipt":{"blockHash":"0x2c218ad7a7f3104edcb11c5fe04699b93a24e39a4f193cc981f8321d88baaacf","blockNumber":6722862,"contractAddress":"0x2366Bb0Ce360465153e0fF2945A14e820E6a1A14","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","result":{"address":"0x2366Bb0Ce360465153e0fF2945A14e820E6a1A14","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"Curation#Curation","hash":"0xf48f23e53e8adc84dd2731b1223dbfc7a88aa1554a050dd886e4f32bf4b47252","networkInteractionId":1,"receipt":{"blockHash":"0x2c218ad7a7f3104edcb11c5fe04699b93a24e39a4f193cc981f8321d88baaacf","blockNumber":6722862,"contractAddress":"0xB20db0C5b472A25913f668bdAeE299880F3761e5","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#Curation","result":{"address":"0xB20db0C5b472A25913f668bdAeE299880F3761e5","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"Curation#GraphCurationToken","hash":"0x42bb5c8a740352fe4ed4296d836ffac44d431f8f2ef3caef87a04f6b73c3a83b","networkInteractionId":1,"receipt":{"blockHash":"0x2c218ad7a7f3104edcb11c5fe04699b93a24e39a4f193cc981f8321d88baaacf","blockNumber":6722862,"contractAddress":"0x85820DB0AbC0f869fF5B8C47d80baD8ce8D23e36","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#GraphCurationToken","result":{"address":"0x85820DB0AbC0f869fF5B8C47d80baD8ce8D23e36","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"EpochManager#EpochManager","hash":"0x9cc51e406b48c153b346fcdd834ff65d3167ce1df8dd5596a07f02e139b92f77","networkInteractionId":1,"receipt":{"blockHash":"0x2c218ad7a7f3104edcb11c5fe04699b93a24e39a4f193cc981f8321d88baaacf","blockNumber":6722862,"contractAddress":"0xaBDda0b824b1581Ad6bE147AE5ED7E42B8D90602","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"EpochManager#EpochManager","result":{"address":"0xaBDda0b824b1581Ad6bE147AE5ED7E42B8D90602","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","hash":"0x245dbac23a75574bbf072a23c55ece60c19fc4928f874704661c7770d4aaf676","networkInteractionId":1,"receipt":{"blockHash":"0x2c218ad7a7f3104edcb11c5fe04699b93a24e39a4f193cc981f8321d88baaacf","blockNumber":6722862,"contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","result":{"address":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#GraphToken","hash":"0x0a085a815d30e599f281fbde7a0df8a8a9ee5090481a33ffc226166bbdf6061e","networkInteractionId":1,"receipt":{"blockHash":"0x2c218ad7a7f3104edcb11c5fe04699b93a24e39a4f193cc981f8321d88baaacf","blockNumber":6722862,"contractAddress":"0xFBdc2dEbD9d3C57c5A61c958edcaA8C3a54c6188","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken","result":{"address":"0xFBdc2dEbD9d3C57c5A61c958edcaA8C3a54c6188","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphTokenGateway#GraphTokenGateway","hash":"0x4e38b4bf3a9619551af22cef109c26563a6dc71930e8a27277af36515e66e969","networkInteractionId":1,"receipt":{"blockHash":"0x2c218ad7a7f3104edcb11c5fe04699b93a24e39a4f193cc981f8321d88baaacf","blockNumber":6722862,"contractAddress":"0x2e2a734Aad8Ff4B60E88b211B0daC398eCC2098c","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphTokenGateway","result":{"address":"0x2e2a734Aad8Ff4B60E88b211B0daC398eCC2098c","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","hash":"0xd25cc7260b9f404196709c9bfd8222de1ca28626fa44050d22983038e053de6e","networkInteractionId":1,"receipt":{"blockHash":"0x598a3cf0cfa92908a08e04fab395f4f5fa4362cb73ce8efccd5a7d65e0ebb650","blockNumber":6722863,"contractAddress":"0xC1Ce222a5A5f0e4CA5beF19cF6f53714288b9FFA","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","result":{"address":"0xC1Ce222a5A5f0e4CA5beF19cF6f53714288b9FFA","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonStakingExtension#ExponentialRebates","hash":"0x648676702a8f33c1289655be95cc8131cf9a1987fccc64da8ab5b7bcfd87743e","networkInteractionId":1,"receipt":{"blockHash":"0x598a3cf0cfa92908a08e04fab395f4f5fa4362cb73ce8efccd5a7d65e0ebb650","blockNumber":6722863,"contractAddress":"0xA018c2419084c2DfC9C321103c2D5a98d4Db137c","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStakingExtension#ExponentialRebates","result":{"address":"0xA018c2419084c2DfC9C321103c2D5a98d4Db137c","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"RewardsManager#RewardsManager","hash":"0x9feb7887395ce34be9acdc287aa24f8bad99ddfa64dcde874322a0895769fc20","networkInteractionId":1,"receipt":{"blockHash":"0x598a3cf0cfa92908a08e04fab395f4f5fa4362cb73ce8efccd5a7d65e0ebb650","blockNumber":6722863,"contractAddress":"0x1c37C0725527C76B9B48DaFcE78673bB7354B3a1","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager","result":{"address":"0x1c37C0725527C76B9B48DaFcE78673bB7354B3a1","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setPauseGuardian","futureId":"Controller#Controller.setPauseGuardian","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Controller#Controller.setPauseGuardian","networkInteraction":{"data":"0x48bde20c00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Controller#Controller.setPauseGuardian","networkInteractionId":1,"nonce":247,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8292233818"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x82a2cb419f3ad7da61f82d6e521e6ae8f19a2458d9e1011005362412fd4570a8"},"type":"TRANSACTION_SEND"} +{"args":["0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"transferOwnership","futureId":"Controller#Controller.transferOwnership","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Controller#Controller.transferOwnership","networkInteraction":{"data":"0xf2fde38b000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Controller#Controller.transferOwnership","networkInteractionId":1,"nonce":248,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8292233818"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x2d8d93226974aafffdeacc6e6be418cd8472f6ab42c211d3ef7658e80916b3a1"},"type":"TRANSACTION_SEND"} +{"args":["0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"transferOwnership","futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","networkInteraction":{"data":"0xf2fde38b000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","networkInteractionId":1,"nonce":249,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8292233818"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x0a827a872f000619854e1d5e460db2c1411618130552970dfb12d0345253f4ec"},"type":"TRANSACTION_SEND"} +{"args":["0x559081d91f5ff43dfe51a07c216f8e6893805b35"],"artifactId":"GraphToken#GraphToken","dependencies":["GraphToken#GraphToken"],"functionName":"initialize","futureId":"GraphToken#encodeFunctionCall(GraphToken#GraphToken.initialize)","result":"0xc4d66de8000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","constructorArgs":["0x2366Bb0Ce360465153e0fF2945A14e820E6a1A14","0x559081d91f5ff43dfe51a07c216f8e6893805b35","0x"],"contractName":"TransparentUpgradeableProxy","dependencies":["HorizonProxies#OZProxyDummy_GraphPayments"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","networkInteraction":{"data":"0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61030000000000000000000000002366bb0ce360465153e0ff2945a14e820e6a1a14000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b3500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","networkInteractionId":1,"nonce":250,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8530810126"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x19ff4d52201ce3f6f1d95b72fb8899c8d43797770abbb9f4ae0abedc2db2662a"},"type":"TRANSACTION_SEND"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","constructorArgs":["0xC1Ce222a5A5f0e4CA5beF19cF6f53714288b9FFA","0x559081d91f5ff43dfe51a07c216f8e6893805b35","0x"],"contractName":"TransparentUpgradeableProxy","dependencies":["HorizonProxies#OZProxyDummy_PaymentsEscrow"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","networkInteraction":{"data":"0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000c1ce222a5a5f0e4ca5bef19cf6f53714288b9ffa000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b3500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","networkInteractionId":1,"nonce":251,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8530810126"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x42bf8596317bc2393e34ffebe49928d14bc6c34e67e299839abb86e0b134bb0a"},"type":"TRANSACTION_SEND"} +{"futureId":"Controller#Controller.setPauseGuardian","hash":"0x82a2cb419f3ad7da61f82d6e521e6ae8f19a2458d9e1011005362412fd4570a8","networkInteractionId":1,"receipt":{"blockHash":"0xf260409b3c19df19525b0420481a6647971e2a35465dc5b8a05fde789c1259a6","blockNumber":6722868,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x","logIndex":92,"topics":["0x0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Controller#Controller.setPauseGuardian","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"Controller#Controller.transferOwnership","hash":"0x2d8d93226974aafffdeacc6e6be418cd8472f6ab42c211d3ef7658e80916b3a1","networkInteractionId":1,"receipt":{"blockHash":"0xa59bf740f159ad108f273ba411d5cca144e9593b7af9bb99dc31eddde2a3c419","blockNumber":6722869,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x","logIndex":103,"topics":["0x76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Controller#Controller.transferOwnership","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","hash":"0x0a827a872f000619854e1d5e460db2c1411618130552970dfb12d0345253f4ec","networkInteractionId":1,"receipt":{"blockHash":"0xa59bf740f159ad108f273ba411d5cca144e9593b7af9bb99dc31eddde2a3c419","blockNumber":6722869,"logs":[{"address":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","data":"0x","logIndex":104,"topics":["0x76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","hash":"0x19ff4d52201ce3f6f1d95b72fb8899c8d43797770abbb9f4ae0abedc2db2662a","networkInteractionId":1,"receipt":{"blockHash":"0xa59bf740f159ad108f273ba411d5cca144e9593b7af9bb99dc31eddde2a3c419","blockNumber":6722869,"contractAddress":"0x5C72b84F619399087Df1e4b686050A5F336126D9","logs":[{"address":"0x5C72b84F619399087Df1e4b686050A5F336126D9","data":"0x","logIndex":105,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x0000000000000000000000002366bb0ce360465153e0ff2945a14e820e6a1a14"]},{"address":"0xaBE1e45c636a27aD02f0022e0AB32BF350702Df1","data":"0x","logIndex":106,"topics":["0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35"]},{"address":"0x5C72b84F619399087Df1e4b686050A5F336126D9","data":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abe1e45c636a27ad02f0022e0ab32bf350702df1","logIndex":107,"topics":["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","result":{"address":"0x5C72b84F619399087Df1e4b686050A5F336126D9","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","hash":"0x42bf8596317bc2393e34ffebe49928d14bc6c34e67e299839abb86e0b134bb0a","networkInteractionId":1,"receipt":{"blockHash":"0xa59bf740f159ad108f273ba411d5cca144e9593b7af9bb99dc31eddde2a3c419","blockNumber":6722869,"contractAddress":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","logs":[{"address":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","data":"0x","logIndex":108,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x000000000000000000000000c1ce222a5a5f0e4ca5bef19cf6f53714288b9ffa"]},{"address":"0x9fa225C2D4Cf40c8B0100Af7dacb8bCf84D822d0","data":"0x","logIndex":109,"topics":["0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35"]},{"address":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009fa225c2d4cf40c8b0100af7dacb8bcf84d822d0","logIndex":110,"topics":["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","result":{"address":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"BridgeEscrow#GraphProxy","constructorArgs":["0xD1e69Dd541597F3a976ec34416F806322C560509","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"contractName":"GraphProxy","dependencies":["BridgeEscrow#BridgeEscrow","GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"BridgeEscrow#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"BridgeEscrow#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000d1e69dd541597f3a976ec34416f806322c56050900000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"BridgeEscrow#GraphProxy","networkInteractionId":1,"nonce":252,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8259383240"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xaba3c4f45ab6210c8f50850dc6750ca5fb3eeb757662caf2b496954ddd41303f"},"type":"TRANSACTION_SEND"} +{"args":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841"],"artifactId":"BridgeEscrow#BridgeEscrow","dependencies":["BridgeEscrow#BridgeEscrow","Controller#Controller"],"functionName":"initialize","futureId":"BridgeEscrow#encodeFunctionCall(BridgeEscrow#BridgeEscrow.initialize)","result":"0xc4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"Curation#GraphProxy","constructorArgs":["0xB20db0C5b472A25913f668bdAeE299880F3761e5","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"contractName":"GraphProxy","dependencies":["Curation#Curation","GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"Curation#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000b20db0c5b472a25913f668bdaee299880f3761e500000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#GraphProxy","networkInteractionId":1,"nonce":253,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8259383240"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x3559487111caf96c193099190a2f8e715045161ab114e6016603602bfa965d15"},"type":"TRANSACTION_SEND"} +{"args":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","0x85820DB0AbC0f869fF5B8C47d80baD8ce8D23e36",10000,1],"artifactId":"Curation#Curation","dependencies":["Curation#Curation","Controller#Controller","Curation#GraphCurationToken"],"functionName":"initialize","futureId":"Curation#encodeFunctionCall(Curation#Curation.initialize)","result":"0x4c8c7a440000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e6084100000000000000000000000085820db0abc0f869ff5b8c47d80bad8ce8d23e3600000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000001","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"EpochManager#GraphProxy","constructorArgs":["0xaBDda0b824b1581Ad6bE147AE5ED7E42B8D90602","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"contractName":"GraphProxy","dependencies":["EpochManager#EpochManager","GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"EpochManager#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"EpochManager#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000abdda0b824b1581ad6be147ae5ed7e42b8d9060200000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"EpochManager#GraphProxy","networkInteractionId":1,"nonce":254,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8107471538"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x745091e1d096c3931da1ca2a083308a61367ca0febeb3b45d791fe4ff0466f27"},"type":"TRANSACTION_SEND"} +{"args":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841",60],"artifactId":"EpochManager#EpochManager","dependencies":["EpochManager#EpochManager","Controller#Controller"],"functionName":"initialize","futureId":"EpochManager#encodeFunctionCall(EpochManager#EpochManager.initialize)","result":"0xcd6dc6870000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841000000000000000000000000000000000000000000000000000000000000003c","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"args":["0xed734418922426bf2cc8783754bd80fc4d441a4dbe994549aee8a2f03136fcdb","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","networkInteraction":{"data":"0xe0e99292ed734418922426bf2cc8783754bd80fc4d441a4dbe994549aee8a2f03136fcdb00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","networkInteractionId":1,"nonce":255,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8107471538"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x6c7d7a87d6e93a98eac74bd1174eb67be69e264ba30130faa3ef20985c4f840e"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphToken#GraphProxy","constructorArgs":["0xFBdc2dEbD9d3C57c5A61c958edcaA8C3a54c6188","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"contractName":"GraphProxy","dependencies":["GraphToken#GraphToken","GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"GraphToken#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000fbdc2debd9d3c57c5a61c958edcaa8c3a54c618800000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphProxy","networkInteractionId":1,"nonce":256,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8107471538"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xafd66ceed871485492119031b77cefbaab04cb4d7232abf6f964ec94db1b68db"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphTokenGateway#GraphProxy","constructorArgs":["0x2e2a734Aad8Ff4B60E88b211B0daC398eCC2098c","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"contractName":"GraphProxy","dependencies":["GraphTokenGateway#GraphTokenGateway","GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"GraphTokenGateway#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c0000000000000000000000002e2a734aad8ff4b60e88b211b0dac398ecc2098c00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphProxy","networkInteractionId":1,"nonce":257,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8107471538"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xa9f5e0d14952a90994039d47f916d22788c3f7ba63906a5082d57013cd8c2a30"},"type":"TRANSACTION_SEND"} +{"args":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841"],"artifactId":"GraphTokenGateway#GraphTokenGateway","dependencies":["GraphTokenGateway#GraphTokenGateway","Controller#Controller"],"functionName":"initialize","futureId":"GraphTokenGateway#encodeFunctionCall(GraphTokenGateway#GraphTokenGateway.initialize)","result":"0xc4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","dependencies":["HorizonProxies#TransparentUpgradeableProxy_GraphPayments"],"emitterAddress":"0x5C72b84F619399087Df1e4b686050A5F336126D9","eventIndex":0,"eventName":"AdminChanged","futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments_AdminChanged","nameOrIndex":"newAdmin","result":"0xaBE1e45c636a27aD02f0022e0AB32BF350702Df1","strategy":"basic","strategyConfig":{},"txToReadFrom":"0x19ff4d52201ce3f6f1d95b72fb8899c8d43797770abbb9f4ae0abedc2db2662a","type":"READ_EVENT_ARGUMENT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","dependencies":["HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow"],"emitterAddress":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","eventIndex":0,"eventName":"AdminChanged","futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow_AdminChanged","nameOrIndex":"newAdmin","result":"0x9fa225C2D4Cf40c8B0100Af7dacb8bCf84D822d0","strategy":"basic","strategyConfig":{},"txToReadFrom":"0x42bf8596317bc2393e34ffebe49928d14bc6c34e67e299839abb86e0b134bb0a","type":"READ_EVENT_ARGUMENT_EXECUTION_STATE_INITIALIZE"} +{"args":["0x88cae14a9889b95b4cfd9472fc7dcbca2da791846a1e314bac9c1f8a234cbf9f","0x5C72b84F619399087Df1e4b686050A5F336126D9"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","HorizonProxies#TransparentUpgradeableProxy_GraphPayments"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"HorizonProxies#setContractProxy_GraphPayments","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","networkInteraction":{"data":"0xe0e9929288cae14a9889b95b4cfd9472fc7dcbca2da791846a1e314bac9c1f8a234cbf9f0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d9","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","networkInteractionId":1,"nonce":258,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"7657588232"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xf1a30501c799c04a49362aee92f8207b96e92163b923c47851fea6efc8ed03b7"},"type":"TRANSACTION_SEND"} +{"args":["0x628f67391f8b955553cabfadbf5f1b6a31d2a2d0fea175f5594af9d40b0bedc9","0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","networkInteraction":{"data":"0xe0e99292628f67391f8b955553cabfadbf5f1b6a31d2a2d0fea175f5594af9d40b0bedc90000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","networkInteractionId":1,"nonce":259,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"7657588232"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x48d7e2b18b7d7ad9ad26a6d49fc1bc22c8dad2b92d09dc38328664b19777f726"},"type":"TRANSACTION_SEND"} +{"artifactId":"RewardsManager#GraphProxy","constructorArgs":["0x1c37C0725527C76B9B48DaFcE78673bB7354B3a1","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"contractName":"GraphProxy","dependencies":["RewardsManager#RewardsManager","GraphProxyAdmin#GraphProxyAdmin"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"RewardsManager#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c0000000000000000000000001c37c0725527c76b9b48dafce78673bb7354b3a100000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#GraphProxy","networkInteractionId":1,"nonce":260,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"7657588232"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xee72027f07a720c2696d22ef0b2bdc0c82d8d1c0febc8f1e21e5a2b560712e9f"},"type":"TRANSACTION_SEND"} +{"args":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841"],"artifactId":"RewardsManager#RewardsManager","dependencies":["RewardsManager#RewardsManager","Controller#Controller"],"functionName":"initialize","futureId":"RewardsManager#encodeFunctionCall(RewardsManager#RewardsManager.initialize)","result":"0xc4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"futureId":"BridgeEscrow#GraphProxy","hash":"0xaba3c4f45ab6210c8f50850dc6750ca5fb3eeb757662caf2b496954ddd41303f","networkInteractionId":1,"receipt":{"blockHash":"0x616cd1414f425239dc786292953e73fcff86c7f23fc3cca0f6feae4c33b423c1","blockNumber":6722875,"contractAddress":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","logs":[{"address":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","data":"0x","logIndex":124,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416"]},{"address":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","data":"0x","logIndex":125,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000d1e69dd541597f3a976ec34416f806322c560509"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"BridgeEscrow#GraphProxy","result":{"address":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"Curation#GraphProxy","hash":"0x3559487111caf96c193099190a2f8e715045161ab114e6016603602bfa965d15","networkInteractionId":1,"receipt":{"blockHash":"0x616cd1414f425239dc786292953e73fcff86c7f23fc3cca0f6feae4c33b423c1","blockNumber":6722875,"contractAddress":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","logs":[{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x","logIndex":132,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416"]},{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x","logIndex":133,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000b20db0c5b472a25913f668bdaee299880f3761e5"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#GraphProxy","result":{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"EpochManager#GraphProxy","hash":"0x745091e1d096c3931da1ca2a083308a61367ca0febeb3b45d791fe4ff0466f27","networkInteractionId":1,"receipt":{"blockHash":"0x616cd1414f425239dc786292953e73fcff86c7f23fc3cca0f6feae4c33b423c1","blockNumber":6722875,"contractAddress":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","logs":[{"address":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","data":"0x","logIndex":135,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416"]},{"address":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","data":"0x","logIndex":136,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000abdda0b824b1581ad6be147ae5ed7e42b8d90602"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"EpochManager#GraphProxy","result":{"address":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","hash":"0x6c7d7a87d6e93a98eac74bd1174eb67be69e264ba30130faa3ef20985c4f840e","networkInteractionId":1,"receipt":{"blockHash":"0x616cd1414f425239dc786292953e73fcff86c7f23fc3cca0f6feae4c33b423c1","blockNumber":6722875,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","logIndex":147,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xed734418922426bf2cc8783754bd80fc4d441a4dbe994549aee8a2f03136fcdb"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#GraphProxy","hash":"0xafd66ceed871485492119031b77cefbaab04cb4d7232abf6f964ec94db1b68db","networkInteractionId":1,"receipt":{"blockHash":"0xaa3a886e36c88d7260fd67dbe42ffb2f9133fbbba4bfe5ee3f10f0e8aafd280c","blockNumber":6722876,"contractAddress":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","logs":[{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":59,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416"]},{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":60,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000fbdc2debd9d3c57c5a61c958edcaa8c3a54c6188"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphProxy","result":{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphTokenGateway#GraphProxy","hash":"0xa9f5e0d14952a90994039d47f916d22788c3f7ba63906a5082d57013cd8c2a30","networkInteractionId":1,"receipt":{"blockHash":"0xaa3a886e36c88d7260fd67dbe42ffb2f9133fbbba4bfe5ee3f10f0e8aafd280c","blockNumber":6722876,"contractAddress":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","logs":[{"address":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","data":"0x","logIndex":66,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416"]},{"address":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","data":"0x","logIndex":67,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000002e2a734aad8ff4b60e88b211b0dac398ecc2098c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphProxy","result":{"address":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","hash":"0xf1a30501c799c04a49362aee92f8207b96e92163b923c47851fea6efc8ed03b7","networkInteractionId":1,"receipt":{"blockHash":"0xaa3a886e36c88d7260fd67dbe42ffb2f9133fbbba4bfe5ee3f10f0e8aafd280c","blockNumber":6722876,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d9","logIndex":82,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x88cae14a9889b95b4cfd9472fc7dcbca2da791846a1e314bac9c1f8a234cbf9f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","hash":"0x48d7e2b18b7d7ad9ad26a6d49fc1bc22c8dad2b92d09dc38328664b19777f726","networkInteractionId":1,"receipt":{"blockHash":"0xcf942f3624e64065cdb5338f1c83974ff859ee7a89ad9122eb69ad31de7ce4fa","blockNumber":6722877,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x0000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53","logIndex":86,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x628f67391f8b955553cabfadbf5f1b6a31d2a2d0fea175f5594af9d40b0bedc9"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"RewardsManager#GraphProxy","hash":"0xee72027f07a720c2696d22ef0b2bdc0c82d8d1c0febc8f1e21e5a2b560712e9f","networkInteractionId":1,"receipt":{"blockHash":"0xcf942f3624e64065cdb5338f1c83974ff859ee7a89ad9122eb69ad31de7ce4fa","blockNumber":6722877,"contractAddress":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","logs":[{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x","logIndex":89,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416"]},{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x","logIndex":90,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000001c37c0725527c76b9b48dafce78673bb7354b3a1"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#GraphProxy","result":{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"BridgeEscrow#BridgeEscrow_Instance","contractAddress":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","contractName":"BridgeEscrow_Instance","dependencies":["BridgeEscrow#GraphProxy"],"futureId":"BridgeEscrow#BridgeEscrow_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0xD1e69Dd541597F3a976ec34416F806322C560509","0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","0xc4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","BridgeEscrow#BridgeEscrow","BridgeEscrow#GraphProxy","BridgeEscrow#encodeFunctionCall(BridgeEscrow#BridgeEscrow.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"acceptProxyAndCall","futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e000000000000000000000000d1e69dd541597f3a976ec34416f806322c560509000000000000000000000000b8ee971f6281a2ec1634b80d6f9cea713847fa2f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e6084100000000000000000000000000000000000000000000000000000000","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":261,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6465951460"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x124fa6061847919087f7ef029b1aacbaf124047fa6840128e839acf417075aae"},"type":"TRANSACTION_SEND"} +{"artifactId":"Curation#Curation_Instance","contractAddress":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","contractName":"Curation_Instance","dependencies":["Curation#GraphProxy"],"futureId":"Curation#Curation_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0xB20db0C5b472A25913f668bdAeE299880F3761e5","0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","0x4c8c7a440000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e6084100000000000000000000000085820db0abc0f869ff5b8c47d80bad8ce8d23e3600000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000001"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","Curation#Curation","Curation#GraphProxy","Curation#encodeFunctionCall(Curation#Curation.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"acceptProxyAndCall","futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e000000000000000000000000b20db0c5b472a25913f668bdaee299880f3761e5000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000844c8c7a440000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e6084100000000000000000000000085820db0abc0f869ff5b8c47d80bad8ce8d23e360000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":262,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6465951460"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xc397b948ab0c4dfc91733b938d9ba9316eeeee5869bdfecbd08cc07da14bc4f1"},"type":"TRANSACTION_SEND"} +{"artifactId":"EpochManager#EpochManager_Instance","contractAddress":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","contractName":"EpochManager_Instance","dependencies":["EpochManager#GraphProxy"],"futureId":"EpochManager#EpochManager_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0xaBDda0b824b1581Ad6bE147AE5ED7E42B8D90602","0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","0xcd6dc6870000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841000000000000000000000000000000000000000000000000000000000000003c"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","EpochManager#EpochManager","EpochManager#GraphProxy","EpochManager#encodeFunctionCall(EpochManager#EpochManager.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"acceptProxyAndCall","futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e000000000000000000000000abdda0b824b1581ad6be147ae5ed7e42b8d90602000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044cd6dc6870000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":263,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6401501702"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xe061aa58d3a2b55e78f31fcf2783d4ad3d1f1808d5d15d6fb269e215bfb31ac6"},"type":"TRANSACTION_SEND"} +{"args":["0xFBdc2dEbD9d3C57c5A61c958edcaA8C3a54c6188","0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","0xc4d66de8000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","GraphToken#GraphToken","GraphToken#GraphProxy","GraphToken#encodeFunctionCall(GraphToken#GraphToken.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"acceptProxyAndCall","futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e000000000000000000000000fbdc2debd9d3c57c5a61c958edcaa8c3a54c6188000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f20500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b3500000000000000000000000000000000000000000000000000000000","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":264,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6401501702"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x571ffeec4054cefa882cd8eb66651c3acf82fd6eb8b6886540f26d22342d645a"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","contractName":"GraphToken_Instance","dependencies":["GraphToken#GraphProxy"],"futureId":"GraphToken#GraphToken_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0x2e2a734Aad8Ff4B60E88b211B0daC398eCC2098c","0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","0xc4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","GraphTokenGateway#GraphTokenGateway","GraphTokenGateway#GraphProxy","GraphTokenGateway#encodeFunctionCall(GraphTokenGateway#GraphTokenGateway.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"acceptProxyAndCall","futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e0000000000000000000000002e2a734aad8ff4b60e88b211b0dac398ecc2098c000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df5100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e6084100000000000000000000000000000000000000000000000000000000","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":265,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6401501702"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x22570f1c3113274e55b371d826ed28e5338a9b478bd6b100fab13f4b98bc8191"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphTokenGateway#GraphTokenGateway_Instance","contractAddress":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","contractName":"GraphTokenGateway_Instance","dependencies":["GraphTokenGateway#GraphProxy"],"futureId":"GraphTokenGateway#GraphTokenGateway_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#ProxyAdmin_GraphPayments","contractAddress":"0xaBE1e45c636a27aD02f0022e0AB32BF350702Df1","contractName":"ProxyAdmin","dependencies":["HorizonProxies#TransparentUpgradeableProxy_GraphPayments_AdminChanged"],"futureId":"HorizonProxies#ProxyAdmin_GraphPayments","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#ProxyAdmin_PaymentsEscrow","contractAddress":"0x9fa225C2D4Cf40c8B0100Af7dacb8bCf84D822d0","contractName":"ProxyAdmin","dependencies":["HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow_AdminChanged"],"futureId":"HorizonProxies#ProxyAdmin_PaymentsEscrow","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0x1c37C0725527C76B9B48DaFcE78673bB7354B3a1","0xCab63af715010d12dA2128777abB2103F9a0EF8F","0xc4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","RewardsManager#RewardsManager","RewardsManager#GraphProxy","RewardsManager#encodeFunctionCall(RewardsManager#RewardsManager.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"acceptProxyAndCall","futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e0000000000000000000000001c37c0725527c76b9b48dafce78673bb7354b3a1000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e6084100000000000000000000000000000000000000000000000000000000","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":266,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6401501702"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xcd06114d8a95ca26b65ea784390c3a8ba57e2ca7a5e3cf50a34a22488089bb8b"},"type":"TRANSACTION_SEND"} +{"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","contractName":"RewardsManager_Instance","dependencies":["RewardsManager#GraphProxy"],"futureId":"RewardsManager#RewardsManager_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x124fa6061847919087f7ef029b1aacbaf124047fa6840128e839acf417075aae","networkInteractionId":1,"receipt":{"blockHash":"0xfad0d04dab27357db193fa051a3cc2778870ae443464d0c6835efb32e8c74c77","blockNumber":6722882,"logs":[{"address":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","data":"0x","logIndex":137,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000d1e69dd541597f3a976ec34416f806322c560509"]},{"address":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","data":"0x","logIndex":138,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000d1e69dd541597f3a976ec34416f806322c560509","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xB8Ee971F6281a2ec1634b80d6F9CEA713847Fa2F","data":"0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","logIndex":139,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0xc397b948ab0c4dfc91733b938d9ba9316eeeee5869bdfecbd08cc07da14bc4f1","networkInteractionId":1,"receipt":{"blockHash":"0x148f5b2d08a53f325baee4f3ad775ebcdc997eaaa9483d03a5d9878597418bf2","blockNumber":6722883,"logs":[{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x","logIndex":294,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000b20db0c5b472a25913f668bdaee299880f3761e5"]},{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x","logIndex":295,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000b20db0c5b472a25913f668bdaee299880f3761e5","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","logIndex":296,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]},{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656661756c7452657365727665526174696f00000000000000000000000000","logIndex":297,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]},{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000156375726174696f6e54617850657263656e746167650000000000000000000000","logIndex":298,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]},{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000166d696e696d756d4375726174696f6e4465706f73697400000000000000000000","logIndex":299,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]},{"address":"0xEC2ed45a73BD2A324739691eaf425aDD66918FAb","data":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000136375726174696f6e546f6b656e4d617374657200000000000000000000000000","logIndex":300,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0xe061aa58d3a2b55e78f31fcf2783d4ad3d1f1808d5d15d6fb269e215bfb31ac6","networkInteractionId":1,"receipt":{"blockHash":"0x148f5b2d08a53f325baee4f3ad775ebcdc997eaaa9483d03a5d9878597418bf2","blockNumber":6722883,"logs":[{"address":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","data":"0x","logIndex":325,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000abdda0b824b1581ad6be147ae5ed7e42b8d90602"]},{"address":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","data":"0x","logIndex":326,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000abdda0b824b1581ad6be147ae5ed7e42b8d90602","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","data":"0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","logIndex":327,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]},{"address":"0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA","data":"0x000000000000000000000000000000000000000000000000000000000000003c","logIndex":328,"topics":["0x25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce2441","0x0000000000000000000000000000000000000000000000000000000000000001"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x571ffeec4054cefa882cd8eb66651c3acf82fd6eb8b6886540f26d22342d645a","networkInteractionId":1,"receipt":{"blockHash":"0x148f5b2d08a53f325baee4f3ad775ebcdc997eaaa9483d03a5d9878597418bf2","blockNumber":6722883,"logs":[{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":363,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000fbdc2debd9d3c57c5a61c958edcaa8c3a54c6188"]},{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":364,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000fbdc2debd9d3c57c5a61c958edcaa8c3a54c6188","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x0000000000000000000000000000000000000000000000000000000000000000","logIndex":365,"topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35"]},{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":366,"topics":["0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6","0x000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x22570f1c3113274e55b371d826ed28e5338a9b478bd6b100fab13f4b98bc8191","networkInteractionId":1,"receipt":{"blockHash":"0x148f5b2d08a53f325baee4f3ad775ebcdc997eaaa9483d03a5d9878597418bf2","blockNumber":6722883,"logs":[{"address":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","data":"0x","logIndex":373,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000002e2a734aad8ff4b60e88b211b0dac398ecc2098c"]},{"address":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","data":"0x","logIndex":374,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000002e2a734aad8ff4b60e88b211b0dac398ecc2098c","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","data":"0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","logIndex":375,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0xcd06114d8a95ca26b65ea784390c3a8ba57e2ca7a5e3cf50a34a22488089bb8b","networkInteractionId":1,"receipt":{"blockHash":"0x148f5b2d08a53f325baee4f3ad775ebcdc997eaaa9483d03a5d9878597418bf2","blockNumber":6722883,"logs":[{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x","logIndex":379,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000001c37c0725527c76b9b48dafce78673bb7354b3a1"]},{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x","logIndex":380,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000001c37c0725527c76b9b48dafce78673bb7354b3a1","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841","logIndex":381,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f","0xEC2ed45a73BD2A324739691eaf425aDD66918FAb"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","Curation#Curation_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_Curation","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","networkInteraction":{"data":"0xe0e99292e6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","networkInteractionId":1,"nonce":267,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5967649936"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x9f89d2bf81ab5ac286033aff88987d90d1348afd64f486a2d2f23e7e8798fbbd"},"type":"TRANSACTION_SEND"} +{"args":["0xc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f67063","0xC37fccCAc63cC5EeCE1546cE4965651991B74FEA"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","EpochManager#EpochManager_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","networkInteraction":{"data":"0xe0e99292c713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f67063000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","networkInteractionId":1,"nonce":268,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5967649936"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x04fb2e7adda06b235db1ba11dc6f4e4ccb6ef47f32d9941ba515c6c6cf1679be"},"type":"TRANSACTION_SEND"} +{"args":["0x559081d91f5ff43dfe51a07c216f8e6893805b35",{"_kind":"bigint","value":"10000000000000000000000000000"}],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","dependencies":["GraphToken#GraphToken_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"mint","futureId":"GraphToken#GraphToken_Instance.mint","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken_Instance.mint","networkInteraction":{"data":"0x40c10f19000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b350000000000000000000000000000000000000000204fce5e3e25026110000000","id":1,"to":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken_Instance.mint","networkInteractionId":1,"nonce":269,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5967649936"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xabe9021a26f23d28ec71012ac386d34fdea2ef7084efd35616121894f645c65a"},"type":"TRANSACTION_SEND"} +{"args":[],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","dependencies":["GraphToken#GraphToken_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"renounceMinter","futureId":"GraphToken#GraphToken_Instance.renounceMinter","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","networkInteraction":{"data":"0x98650275","id":1,"to":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","networkInteractionId":1,"nonce":270,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5967649936"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xdff51cf961951b65fefe3797283caca05d5f31af940cb1270f47b02cbce21ecd"},"type":"TRANSACTION_SEND"} +{"args":["0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0"],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","dependencies":["GraphToken#GraphToken_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"transferOwnership","futureId":"GraphToken#GraphToken_Instance.transferOwnership","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","networkInteraction":{"data":"0xf2fde38b000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0","id":1,"to":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","networkInteractionId":1,"nonce":271,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5967649936"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xadf29a070eb17da632bb1732743b5b1600a93420584dacf6ccea645937a35c87"},"type":"TRANSACTION_SEND"} +{"args":["0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC"],"artifactId":"GraphTokenGateway#GraphTokenGateway_Instance","contractAddress":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","dependencies":["GraphTokenGateway#GraphTokenGateway_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setPauseGuardian","futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","networkInteraction":{"data":"0x48bde20c00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc","id":1,"to":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","networkInteractionId":1,"nonce":272,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5967649936"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x5ad72c15da902d4654d640998f7cabf0a5da9c7d59a6b3f90cf90fea180cf538"},"type":"TRANSACTION_SEND"} +{"args":[{"_kind":"bigint","value":"114155251141552511415"}],"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","dependencies":["RewardsManager#RewardsManager_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setIssuancePerBlock","futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","networkInteraction":{"data":"0x1156bdc10000000000000000000000000000000000000000000000063038ec17c1be19b7","id":1,"to":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","networkInteractionId":1,"nonce":273,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5685787546"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x86215f9b3ea77233196ae624039bd1ef3626349789845ef23f6b223267d09fb6"},"type":"TRANSACTION_SEND"} +{"args":["0xd03ea8624C8C5987235048901fB614fDcA89b117"],"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","dependencies":["RewardsManager#RewardsManager_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setSubgraphAvailabilityOracle","futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","networkInteraction":{"data":"0x0903c094000000000000000000000000d03ea8624c8c5987235048901fb614fdca89b117","id":1,"to":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","networkInteractionId":1,"nonce":274,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5685787546"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x0db978a6567fb3d8e822a379f50e5007c2a6c99b6da8fd1c82e5fabe4e83f381"},"type":"TRANSACTION_SEND"} +{"args":["0x0000000000000000000000000000000000000000"],"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","dependencies":["RewardsManager#RewardsManager_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setSubgraphService","futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","networkInteraction":{"data":"0x93a90a1e0000000000000000000000000000000000000000000000000000000000000000","id":1,"to":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","networkInteractionId":1,"nonce":275,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5685787546"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xfd1398d59b8f2325ccc4591459416cf624b7de117009050c869cc5512c11d406"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","hash":"0x9f89d2bf81ab5ac286033aff88987d90d1348afd64f486a2d2f23e7e8798fbbd","networkInteractionId":1,"receipt":{"blockHash":"0x3dec6ec446a3e0bb8b7343115abddf21883724854f7a164a402dd6fe02da133f","blockNumber":6722888,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab","logIndex":171,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","hash":"0x04fb2e7adda06b235db1ba11dc6f4e4ccb6ef47f32d9941ba515c6c6cf1679be","networkInteractionId":1,"receipt":{"blockHash":"0x3dec6ec446a3e0bb8b7343115abddf21883724854f7a164a402dd6fe02da133f","blockNumber":6722888,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea","logIndex":172,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f67063"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#GraphToken_Instance.mint","hash":"0xabe9021a26f23d28ec71012ac386d34fdea2ef7084efd35616121894f645c65a","networkInteractionId":1,"receipt":{"blockHash":"0x3dec6ec446a3e0bb8b7343115abddf21883724854f7a164a402dd6fe02da133f","blockNumber":6722888,"logs":[{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x0000000000000000000000000000000000000000204fce5e3e25026110000000","logIndex":173,"topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken_Instance.mint","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","hash":"0xdff51cf961951b65fefe3797283caca05d5f31af940cb1270f47b02cbce21ecd","networkInteractionId":1,"receipt":{"blockHash":"0x3dec6ec446a3e0bb8b7343115abddf21883724854f7a164a402dd6fe02da133f","blockNumber":6722888,"logs":[{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":174,"topics":["0xe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb66692","0x000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","hash":"0xadf29a070eb17da632bb1732743b5b1600a93420584dacf6ccea645937a35c87","networkInteractionId":1,"receipt":{"blockHash":"0x5c67a0115a982045355c417af43b65a3396b770cd887d7cc8f146d1c20cce8c4","blockNumber":6722889,"logs":[{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":76,"topics":["0x76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","hash":"0x5ad72c15da902d4654d640998f7cabf0a5da9c7d59a6b3f90cf90fea180cf538","networkInteractionId":1,"receipt":{"blockHash":"0x5c67a0115a982045355c417af43b65a3396b770cd887d7cc8f146d1c20cce8c4","blockNumber":6722889,"logs":[{"address":"0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51","data":"0x","logIndex":83,"topics":["0x0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","hash":"0x86215f9b3ea77233196ae624039bd1ef3626349789845ef23f6b223267d09fb6","networkInteractionId":1,"receipt":{"blockHash":"0x5c67a0115a982045355c417af43b65a3396b770cd887d7cc8f146d1c20cce8c4","blockNumber":6722889,"logs":[{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001069737375616e6365506572426c6f636b00000000000000000000000000000000","logIndex":87,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","hash":"0x0db978a6567fb3d8e822a379f50e5007c2a6c99b6da8fd1c82e5fabe4e83f381","networkInteractionId":1,"receipt":{"blockHash":"0x5c67a0115a982045355c417af43b65a3396b770cd887d7cc8f146d1c20cce8c4","blockNumber":6722889,"logs":[{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a7375626772617068417661696c6162696c6974794f7261636c65000000000000","logIndex":95,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","hash":"0xfd1398d59b8f2325ccc4591459416cf624b7de117009050c869cc5512c11d406","networkInteractionId":1,"receipt":{"blockHash":"0xdf113cab335f161d85a31f21abbf0e3586a36b94094af6dce4af90db6f6d0633","blockNumber":6722891,"logs":[{"address":"0xCab63af715010d12dA2128777abB2103F9a0EF8F","data":"0x","logIndex":89,"topics":["0x97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0","0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","GraphTokenGateway#GraphTokenGateway_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","networkInteraction":{"data":"0xe0e99292d362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df51","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","networkInteractionId":1,"nonce":276,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6928415834"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x822f9af7a805bf25b6478d2b8ffae452adc5b17b3bdf006f711e1a3e821925ad"},"type":"TRANSACTION_SEND"} +{"args":["0x966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c53180761","0xCab63af715010d12dA2128777abB2103F9a0EF8F"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","RewardsManager#RewardsManager_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","networkInteraction":{"data":"0xe0e99292966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c53180761000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","networkInteractionId":1,"nonce":277,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"6928415834"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x0aad2a8d6af0acb52bbfdb68eaf747dfb918ebe060794dd32432d51b694e3eda"},"type":"TRANSACTION_SEND"} +{"args":["0xB0F7E9E2cEcD3E93373DC3979f8108E4C595Df51"],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","dependencies":["GraphToken#GraphToken_Instance","GraphTokenGateway#GraphTokenGateway_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"addMinter","futureId":"GraphToken#addMinterGateway","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#addMinterGateway","networkInteraction":{"data":"0x983b2d56000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df51","id":1,"to":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#addMinterGateway","networkInteractionId":1,"nonce":278,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"7784085492"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xc7ea73b0f63ce90fe81dd9a64a9b62e803d4733536bc1fb7a4a92cd9117429e1"},"type":"TRANSACTION_SEND"} +{"args":["0xCab63af715010d12dA2128777abB2103F9a0EF8F"],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","dependencies":["GraphToken#GraphToken_Instance","RewardsManager#RewardsManager_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"addMinter","futureId":"GraphToken#addMinterRewardsManager","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#addMinterRewardsManager","networkInteraction":{"data":"0x983b2d56000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f","id":1,"to":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#addMinterRewardsManager","networkInteractionId":1,"nonce":279,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"7784085492"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xf25f5506534737afc12ef13f2ce46d7bbefef65e4ae0e4051f0a545da5a66520"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","hash":"0x822f9af7a805bf25b6478d2b8ffae452adc5b17b3bdf006f711e1a3e821925ad","networkInteractionId":1,"receipt":{"blockHash":"0x311163e088954bb322ddc81e61ad733929129f310e4a01f9088f5cbefbf744ad","blockNumber":6722897,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df51","logIndex":143,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","hash":"0x0aad2a8d6af0acb52bbfdb68eaf747dfb918ebe060794dd32432d51b694e3eda","networkInteractionId":1,"receipt":{"blockHash":"0x311163e088954bb322ddc81e61ad733929129f310e4a01f9088f5cbefbf744ad","blockNumber":6722897,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f","logIndex":146,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c53180761"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#addMinterGateway","hash":"0xc7ea73b0f63ce90fe81dd9a64a9b62e803d4733536bc1fb7a4a92cd9117429e1","networkInteractionId":1,"receipt":{"blockHash":"0x311163e088954bb322ddc81e61ad733929129f310e4a01f9088f5cbefbf744ad","blockNumber":6722897,"logs":[{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":147,"topics":["0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6","0x000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df51"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#addMinterGateway","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#addMinterRewardsManager","hash":"0xf25f5506534737afc12ef13f2ce46d7bbefef65e4ae0e4051f0a545da5a66520","networkInteractionId":1,"receipt":{"blockHash":"0x417b6b008fcb87166d70b296900cb668a01ad4b4ce0ecf8bd46694eb5e7e286c","blockNumber":6722898,"logs":[{"address":"0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205","data":"0x","logIndex":79,"topics":["0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6","0x000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#addMinterRewardsManager","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247","0xeC385b1c7e34E47A71E1CB326D172Fdf2207F205"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","GraphToken#GraphToken_Instance"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","networkInteraction":{"data":"0xe0e9929245fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f205","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","networkInteractionId":1,"nonce":280,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"8636477458"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x5d3310d0fe09bef38f2cfd5b1dc229af2fa7362bc43f78db3f3ec13149df17b9"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","hash":"0x5d3310d0fe09bef38f2cfd5b1dc229af2fa7362bc43f78db3f3ec13149df17b9","networkInteractionId":1,"receipt":{"blockHash":"0x43f6f070dfc12e319cecac0d5bd740accb53e00a25d01866dc46c87d35ecd2f8","blockNumber":6722903,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f205","logIndex":118,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphHorizon_Periphery#Dummy","constructorArgs":[],"contractName":"Dummy","dependencies":["GraphHorizon_Periphery#setContractProxy_EpochManager","GraphHorizon_Periphery#setContractProxy_RewardsManager","GraphHorizon_Periphery#setContractProxy_GraphToken","GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","GraphHorizon_Periphery#setContractProxy_Curation"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"GraphHorizon_Periphery#Dummy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#Dummy","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#Dummy","networkInteractionId":1,"nonce":281,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"7026461560"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x746c4897096ec80bb89d5bc684cd2a45293680779f1150fac7856ba71e8e5d25"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#Dummy","hash":"0x746c4897096ec80bb89d5bc684cd2a45293680779f1150fac7856ba71e8e5d25","networkInteractionId":1,"receipt":{"blockHash":"0xc19d57434203d1b45be2ee82dfd7360ae6ff772cb824d9bab62d60d139bec49e","blockNumber":6722908,"contractAddress":"0x31a62E69D8A4003365A97758091685eA72333155","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#Dummy","result":{"address":"0x31a62E69D8A4003365A97758091685eA72333155","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonProxies#GraphProxy_HorizonStaking","constructorArgs":["0x0000000000000000000000000000000000000000","0x86e0221dBe437a67120BdBB8c53847Fb4D756416"],"contractName":"GraphProxy","dependencies":["GraphProxyAdmin#GraphProxyAdmin","GraphHorizon_Periphery#Dummy"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonProxies#GraphProxy_HorizonStaking","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","networkInteractionId":1,"nonce":282,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5646202602"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xde123168b7a62525b1bd57dfb48ff1d3665c85c624875cf36b488153359ab35f"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","hash":"0xde123168b7a62525b1bd57dfb48ff1d3665c85c624875cf36b488153359ab35f","networkInteractionId":1,"receipt":{"blockHash":"0x678427d0801a7b00fa93b3e19f2b9c7971dabcb924bc7e7cf67a173913ad458a","blockNumber":6722913,"contractAddress":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","logs":[{"address":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","data":"0x","logIndex":110,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416"]},{"address":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","data":"0x","logIndex":111,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","result":{"address":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034","0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2"],"artifactId":"Controller#Controller","contractAddress":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","dependencies":["Controller#Controller","HorizonProxies#GraphProxy_HorizonStaking"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"setContractProxy","futureId":"HorizonProxies#setContractProxy_HorizonStaking","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","networkInteraction":{"data":"0xe0e992921df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","id":1,"to":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","networkInteractionId":1,"nonce":283,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5297354030"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x49fb9949b5addf8193f55cd13c12a58721048dd388a0e9d0336d4fce275c239e"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","hash":"0x49fb9949b5addf8193f55cd13c12a58721048dd388a0e9d0336d4fce275c239e","networkInteractionId":1,"receipt":{"blockHash":"0xa5e3de6ec030830e11a3da3a3671194b2d541242bbee53d3f0db523b2ae7bc99","blockNumber":6722918,"logs":[{"address":"0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","data":"0x000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","logIndex":235,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonProxies#RegisteredDummy","constructorArgs":[],"contractName":"Dummy","dependencies":["HorizonProxies#setContractProxy_HorizonStaking","HorizonProxies#setContractProxy_GraphPayments","HorizonProxies#setContractProxy_PaymentsEscrow"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonProxies#RegisteredDummy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#RegisteredDummy","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#RegisteredDummy","networkInteractionId":1,"nonce":284,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5396337696"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x0a1ef5a97280f780202692bf5fad5400a9b384cfcc559031f98529d1dd4688a2"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#RegisteredDummy","hash":"0x0a1ef5a97280f780202692bf5fad5400a9b384cfcc559031f98529d1dd4688a2","networkInteractionId":1,"receipt":{"blockHash":"0xdd4d44c64f6a0757998a4a81dfd077575d7cd8fe311513b4fd07bcea1e16414c","blockNumber":6722923,"contractAddress":"0x73bb9ee763C815ae288f5c75187cb3Be2De1DA38","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#RegisteredDummy","result":{"address":"0x73bb9ee763C815ae288f5c75187cb3Be2De1DA38","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphPayments#GraphPayments","constructorArgs":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841",10000],"contractName":"GraphPayments","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"GraphPayments#GraphPayments","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphPayments#GraphPayments","networkInteraction":{"data":"0x6101e060405234801561001157600080fd5b5060405161132f38038061132f833981016040819052610030916104ee565b816001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b290610372565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e590610372565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e90610372565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015890610372565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019090610372565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb90610372565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020990610372565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024590610372565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a90610372565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a45061033a81620f4240101590565b819061035c5760405163d3097bcb60e01b815260040161007191815260200190565b506101c081905261036b610420565b505061058a565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103ad91815260200190565b602060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ee919061051a565b9050826001600160a01b0382166104195760405163218f5add60e11b8152600401610071919061053c565b5092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156104705760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146104cf5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146104e957600080fd5b919050565b6000806040838503121561050157600080fd5b61050a836104d2565b9150602083015190509250929050565b60006020828403121561052c57600080fd5b610535826104d2565b9392505050565b602081526000825180602084015260005b8181101561056a576020818601810151604086840101520161054d565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051610d086106276000396000818160560152610104015260005050600050506000505060005050600050506000505060005050600050506000818161012e015281816102c1015261035401526000818160d5015281816102220152818161025a0152818161029201526103f50152610d086000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b00330000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e608410000000000000000000000000000000000000000000000000000000000002710","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphPayments#GraphPayments","networkInteractionId":1,"nonce":285,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4889646478"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xfc719b86c2b331de4379e5cb9becd1543e98fdec066458bc4c99de313e15c47c"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphPayments#GraphPayments_Instance","contractAddress":"0x5C72b84F619399087Df1e4b686050A5F336126D9","contractName":"GraphPayments","dependencies":["HorizonProxies#TransparentUpgradeableProxy_GraphPayments"],"futureId":"GraphPayments#GraphPayments_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonStakingExtension#HorizonStakingExtension","constructorArgs":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","0x0000000000000000000000000000000000000000"],"contractName":"HorizonStakingExtension","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy","HorizonStakingExtension#ExponentialRebates"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonStakingExtension#HorizonStakingExtension","futureType":"CONTRACT_DEPLOYMENT","libraries":{"ExponentialRebates":"0xA018c2419084c2DfC9C321103c2D5a98d4Db137c"},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","networkInteraction":{"data":"0x6101e060405234801561001157600080fd5b5060405161396738038061396783398101604081905261003091610411565b818181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610347565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610347565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610347565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610347565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610347565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610347565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610347565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610347565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610347565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b03166101c052506104b4915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038291815260200190565b602060405180830381865afa15801561039f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c39190610444565b9050826001600160a01b0382166103ee5760405163218f5add60e11b81526004016100749190610466565b5092915050565b80516001600160a01b038116811461040c57600080fd5b919050565b6000806040838503121561042457600080fd5b61042d836103f5565b915061043b602084016103f5565b90509250929050565b60006020828403121561045657600080fd5b61045f826103f5565b9392505050565b602081526000825180602084015260005b818110156104945760208186018101516040868401015201610477565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516133d761059060003960008181611c3601528181611e3601526123f00152600061205b015260005050600061178501526000818161213d0152818161280501526129080152600081816112c70152611b6f015260008181610bbf01528181610cbc01528181610ed601526116dc015260005050600050506000505060008181611044015281816111fa01528181612023015281816121b20152818161239a015281816124c2015261263201526133d76000f3fe6080604052600436106101f25760003560e01c806398c657dc1161010d578063b6363cf2116100a0578063e2e1e8e91161006f578063e2e1e8e914610a0b578063e73e14bf14610a38578063f1d60d6614610a70578063fb744cc014610a90578063fc54fb2714610ab057600080fd5b8063b6363cf2146108dd578063b7ca724114610927578063c0641994146109c1578063ccebcabb146109dc57600080fd5b8063a4c0ed36116100dc578063a4c0ed3614610837578063a784d49814610857578063ac9650d814610877578063ae4fe67a146108a457600080fd5b806398c657dc1461072d5780639ce7abe51461075a578063a212daf81461077a578063a2594d821461081757600080fd5b8063561285e411610185578063872d048911610154578063872d04891461064c5780638cc01c861461066c5780638d3c100a146106ed5780639054e3431461070d57600080fd5b8063561285e4146105a95780636a3ca383146105fc5780637573ef4f1461062c5780637a7664601461031157600080fd5b806325d9897e116101c157806325d9897e1461036957806339514ad21461047957806344c32a61146104ab57806355c85269146104cb57600080fd5b806308ce5f68146102495780630e0229231461027c5780631787e69f146103115780631ae720451461034757600080fd5b366102445760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b600080fd5b34801561025557600080fd5b50610269610264366004612bec565b610ac8565b6040519081526020015b60405180910390f35b34801561028857600080fd5b5061029c610297366004612c25565b610add565b604051610273919060006101208201905060018060a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b34801561031d57600080fd5b5061026961032c366004612c25565b6001600160a01b03166000908152600e602052604090205490565b34801561035357600080fd5b50610367610362366004612c25565b610bbd565b005b34801561037557600080fd5b5061046c610384366004612bec565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516102739190612c42565b34801561048557600080fd5b50601a546001600160401b03165b6040516001600160401b039091168152602001610273565b3480156104b757600080fd5b506103676104c6366004612cd2565b610cba565b3480156104d757600080fd5b506105776104e6366004612c25565b6001600160a01b039081166000908152600f602090815260408083208151610120810183528154909516808652600182015493860184905260028201549286018390526003820154606087015260048201546080870152600582015460a0870152600682015460c0870152600782015460e08701819052600890920154610100909601959095529394919390929091565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610273565b3480156105b557600080fd5b506105c96105c4366004612bec565b610d68565b60405161027391908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561060857600080fd5b5061061c610617366004612c25565b610df6565b6040519015158152602001610273565b34801561063857600080fd5b50610269610647366004612cfe565b610e1b565b34801561065857600080fd5b50610269610667366004612d4d565b610e7f565b34801561067857600080fd5b506106d2610687366004612c25565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b60408051825181526020928301519281019290925201610273565b3480156106f957600080fd5b50610367610708366004612d96565b610ed4565b34801561071957600080fd5b50610269610728366004612dbb565b6113a0565b34801561073957600080fd5b5061074d610748366004612c25565b611488565b6040516102739190612e11565b34801561076657600080fd5b50610367610775366004612e81565b611493565b34801561078657600080fd5b506105c9610795366004612dbb565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561082357600080fd5b50610367610832366004612c25565b6115be565b34801561084357600080fd5b50610367610852366004612ed5565b6116da565b34801561086357600080fd5b50610269610872366004612c25565b6118e7565b34801561088357600080fd5b50610897610892366004612f30565b6118f2565b6040516102739190612fc9565b3480156108b057600080fd5b5061061c6108bf366004612c25565b6001600160a01b031660009081526022602052604090205460ff1690565b3480156108e957600080fd5b5061061c6108f8366004612bec565b6001600160a01b0380821660009081526015602090815260408083209386168352929052205460ff1692915050565b34801561093357600080fd5b50610996610942366004613049565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b0316908201529181015190820152606001610273565b3480156109cd57600080fd5b50600d5463ffffffff16610493565b3480156109e857600080fd5b506109fc6109f7366004612dbb565b6119d9565b60405190518152602001610273565b348015610a1757600080fd5b50610269610a26366004613049565b60009081526010602052604090205490565b348015610a4457600080fd5b5061061c610a53366004612c25565b6001600160a01b03166000908152600e6020526040902054151590565b348015610a7c57600080fd5b5061061c610a8b366004612c25565b611a2b565b348015610a9c57600080fd5b50610269610aab366004612bec565b611a50565b348015610abc57600080fd5b5060205460ff1661061c565b6000610ad48383611a5c565b90505b92915050565b610b3860405180610120016040528060006001600160a01b0316815260200160008019168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b039081166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e08301526008015461010082015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190613062565b6001600160a01b0316336001600160a01b031614610c7057604051635d9044cd60e01b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0383169081179091556040517f690e9b982dc9aefaa1cfed186a2d2045a638013d658104102c9437235bee4b6090600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c919061307f565b15610d5a57604051632b37d9d160e21b815260040160405180910390fd5b610d648282611a94565b5050565b610d936040518060800160405280600081526020016000815260200160008152602001600081525090565b610dbe6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000610dca8585611e32565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b60006001610e0383611eb6565b6002811115610e1457610e14612dfb565b1492915050565b6001600160a01b038084166000908152601c60209081526040808320938616835292905290812081836002811115610e5557610e55612dfb565b6002811115610e6657610e66612dfb565b81526020019081526020016000205490505b9392505050565b600080610e8c8585611a5c565b90506000610e9a8686611f0f565b90506000610eae63ffffffff8616846130b7565b90506000610ebc8383611f3a565b9050610ec881856130ce565b98975050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061307f565b15610f7457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038116610fb35760405162461bcd60e51b815260206004820152600660248201526521616c6c6f6360d01b604482015260640161023b565b6000610fbe82611eb6565b90506000816002811115610fd457610fd4612dfb565b0361100c5760405162461bcd60e51b81526020600482015260086024820152670858dbdb1b1958dd60c21b604482015260640161023b565b8260000361101957505050565b6001600160a01b0382166000908152600f6020526040812060018101549091859080808061107333867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190611f51565b600d5461108e908690600160401b900463ffffffff1661200e565b935061109a84866130e1565b600d549095506110bb9087908790640100000000900463ffffffff16612047565b92506110c783866130e1565b94508487600501546110d991906130ce565b6005880155600287015460009015806110ff5750601954600160a01b900463ffffffff16155b6111ca5760058801546002890154600d546019546040516349484d8160e01b81526004810194909452602484019290925263ffffffff600160a01b80830482166044860152600160c01b928390048216606486015283048116608485015291041660a482015273A018c2419084c2DfC9C321103c2D5a98d4Db137c906349484d819060c401602060405180830381865af41580156111a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c591906130f4565b6111cd565b60005b90506111dd81896008015461225a565b92506111e98387611f3a565b92506112296111f884886130e1565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690612274565b82156112915782886008015461123f91906130ce565b60088901558754611259906001600160a01b0316846122bc565b915061126582846130e1565b88546001600160a01b03908116600081815260176020526040902054929550611291928692161561234e565b5086546001600160a01b038a8116918891167ff5ded07502b6feba4c13b19a0c6646efd4b4119f439bcbd49076e4f0ed1eec4b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611323573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134791906130f4565b604080516001600160a01b039093168352602083019190915281018f9052606081018990526080810188905260a081018a905260c0810187905260e081018690526101000160405180910390a450505050505050505050565b6001600160a01b038084166000908152601e60209081526040808320868516845282528083209385168352929052908120600381015482036113e6576000915050610e78565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b801561147c576000818152601d602052604090206001810154426001600160401b039091161161146b5760028301546001840154825461145091906130b7565b61145a919061310d565b61146490856130ce565b9350611471565b5061147c565b600201549050611410565b50909695505050505050565b6000610ad782611eb6565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f89190613062565b6001600160a01b0316336001600160a01b0316146115585760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611586908690869060040161312f565b600060405180830381600087803b1580156115a057600080fd5b505af11580156115b4573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116239190613062565b6001600160a01b0316336001600160a01b0316146116835760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156116be57600080fd5b505af11580156116d2573d6000803e3d6000fd5b505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c919061307f565b1561177a57604051632b37d9d160e21b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117e15760405162461bcd60e51b815260206004820152600c60248201526b4f4e4c595f4741544557415960a01b604482015260640161023b565b6018546001600160a01b0385811691161461183e5760405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c315f5354414b494e475f5448524f5547485f4252494447450000604482015260640161023b565b60008061184d838501856131a4565b909250905060ff8216611882576000818060200190518101906118709190613255565b905061187c86826123c4565b506116d2565b60001960ff8316016118b0576000818060200190518101906118a491906132a2565b905061187c86826123d0565b60405162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f434f444560a01b604482015260640161023b565b6000610ad782612740565b604080516000815260208101909152606090826001600160401b0381111561191c5761191c61315e565b60405190808252806020026020018201604052801561194f57816020015b606081526020019060019003908161193a5790505b50915060005b838110156119d1576119ac3086868481811061197357611973613302565b90506020028101906119859190613318565b856040516020016119989392919061335e565b60405160208183030381529060405261278b565b8382815181106119be576119be613302565b6020908102919091010152600101611955565b505092915050565b6040805160208101909152600081526040805160208101909152600081526000611a038686611e32565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b600080611a3783611eb6565b6002811115611a4857611a48612dfb565b141592915050565b6000610ad48383611f0f565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610ad491906130e1565b6000611a9f83611eb6565b90506001816002811115611ab557611ab5612dfb565b14611aec5760405162461bcd60e51b81526020600482015260076024820152662161637469766560c81b604482015260640161023b565b6001600160a01b038381166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600801546101008201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef91906130f4565b608082018190526060820151600091611c079161225a565b9050600082600001516001600160a01b0316336001600160a01b03161480611c78575082516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600090815260156020908152604080832093909416825291909152205460ff165b600d54909150600160801b900463ffffffff1682111580611c9b57506040830151155b15611cd55780611cd55760405162461bcd60e51b8152602060048201526005602482015264042c2eae8d60db1b604482015260640161023b565b60808301516001600160a01b0387166000908152600f6020526040908190206004019190915583015115611db957808015611d0f57508415155b15611d2757611d22868460000151612801565b611d36565b611d3483602001516128e7565b505b60408084015184516001600160a01b03166000908152600e6020529190912060010154611d6391906130e1565b83516001600160a01b03166000908152600e602090815260408083206001019390935582860151818701518352601090915291902054611da391906130e1565b6020808501516000908152601090915260409020555b60208084015184516080808701516040808901518151928352958201959095523394810194909452606084018990528415908401526001600160a01b03808a16939116907ff6725dd105a6fc88bb79a6e4627f128577186c567a17c94818d201c2a4ce14039060a00160405180910390a4505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603611e8b57506001600160a01b0382166000908152601460205260409020610ad7565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610ad7565b6001600160a01b038082166000908152600f6020526040812080549192909116611ee35750600092915050565b600381015415801590611ef857506004810154155b15611f065750600192915050565b50600292915050565b600080611f1c8484611e32565b905080600501548160020154611f3291906130e1565b949350505050565b600081831115611f4a5781610ad4565b5090919050565b8015612009576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061307f565b6120095760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161023b565b505050565b60008061201b8484612975565b9050610ad4817f000000000000000000000000000000000000000000000000000000000000000061121a565b60008260000361205957506000610e78565b7f00000000000000000000000000000000000000000000000000000000000000006000831580159061209357506001600160a01b03821615155b90508080156121065750604051634c4ea0ed60e01b8152600481018790526001600160a01b03831690634c4ea0ed90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612106919061307f565b1561224e5760006121178686612975565b90508015612244576040516307470bfb60e21b8152600481018890526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631d1c2fec906024016020604051808303816000875af1158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa91906130f4565b506121e283827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906129c7565b60405163102ae65160e31b815260048101889052602481018290526001600160a01b03841690638157328890604401600060405180830381600087803b15801561222b57600080fd5b505af115801561223f573d6000803e3d6000fd5b505050505b9250610e78915050565b50600095945050505050565b600081831161226a576000610ad4565b610ad482846130e1565b8015610d6457604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156116be57600080fd5b6001600160a01b03821660009081526014602052604081206002810154829190158015906122fb57508054600160401b900463ffffffff16620f424010155b156123465780546000906123219063ffffffff600160401b9091048116908790612a0216565b905061232d81866130e1565b925082826002015461233f91906130ce565b6002830155505b509392505050565b8260000361235b57505050565b801561236b576120098284612a69565b6001600160a01b03808316600090815260176020526040902054166123be81156123955781612397565b835b857f00000000000000000000000000000000000000000000000000000000000000006121d2565b50505050565b80516120098184612a69565b80516001600160a01b039081166000908152601b602090815260408083207f0000000000000000000000000000000000000000000000000000000000000000909416835292905290812060030154600160601b90046001600160401b031690036124695760405162461bcd60e51b815260206004820152600a60248201526910b83937bb34b9b4b7b760b11b604482015260640161023b565b80516001600160a01b03908116600090815260146020908152604080832082860151909416835260048401909152902060028201541580156124bb575060038201541515806124bb5750600682015415155b156125b5577f0000000000000000000000000000000000000000000000000000000000000000602084015160405163a9059cbb60e01b81526001600160a01b0391821660048201526024810187905291169063a9059cbb906044016020604051808303816000875af1158015612535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612559919061307f565b5082602001516001600160a01b031683600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de866040516125a791815260200190565b60405180910390a350505050565b60008260020154600014806125d1575082600501548360020154145b61260757826005015483600201546125e991906130e1565b60038401546125f890876130b7565b612602919061310d565b612609565b845b905080158061261f5750670de0b6b3a764000085105b156126ae576126548460200151866121d27f000000000000000000000000000000000000000000000000000000000000000090565b83602001516001600160a01b031684600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de876040516126a191815260200190565b60405180910390a3612739565b8483600201546126be91906130ce565b600284015560038301546126d39082906130ce565b600384015581546126e59082906130ce565b82556020808501518551604080518981529384018590526001600160a01b039283169391909216917fcd0366dce5247d874ffc60a762aa7abbb82c1695bbb171609c1b8861e279eb73910160405180910390a35b5050505050565b6001600160a01b0381166000908152600e6020526040812060028101546001820154600483015492549192909161277791906130e1565b61278191906130e1565b610ad791906130e1565b6060600080846001600160a01b0316846040516127a89190613385565b600060405180830381855af49150503d80600081146127e3576040519150601f19603f3d011682016040523d82523d6000602084013e6127e8565b606091505b50915091506127f8858383612ae8565b95945050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000604051636dba849360e11b81526001600160a01b038581166004830152919091169063db750926906024016020604051808303816000875af115801561286e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289291906130f4565b9050806000036128a157505050565b60006128ad8383612b44565b905060006128bb82846130e1565b6001600160a01b038086166000908152601760205260409020549192506127399183918791161561234e565b6040516377561f0760e11b8152600481018290526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063eeac3e0e906024016020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad791906130f4565b600061298482620f4240101590565b82906129a657604051633dc311df60e01b815260040161023b91815260200190565b506129bd6129b783620f42406130e1565b84612a02565b610ad490846130e1565b80156120095760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401611f8e565b6000612a1183620f4240101590565b80612a245750612a2482620f4240101590565b83839091612a4e5760405163768bf0eb60e11b81526004810192909252602482015260440161023b565b50620f42409050612a5f83856130b7565b610ad4919061310d565b6001600160a01b0382166000908152600e6020526040902054612a8d9082906130ce565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290612adc9084815260200190565b60405180910390a25050565b606082612afd57612af882612bab565b610e78565b8151158015612b1457506001600160a01b0384163b155b15612b3d57604051639996b31560e01b81526001600160a01b038516600482015260240161023b565b5080610e78565b6001600160a01b0382166000908152601460205260408120600281015482919015801590612b8457508054640100000000900463ffffffff16620f424010155b156123465780546000906123219063ffffffff6401000000009091048116908790612a0216565b805115612bbb5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114612bd457600080fd5b60008060408385031215612bff57600080fd5b8235612c0a81612bd7565b91506020830135612c1a81612bd7565b809150509250929050565b600060208284031215612c3757600080fd5b8135610ad481612bd7565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151612cb060c084018263ffffffff169052565b5060e0830151612ccb60e08401826001600160401b03169052565b5092915050565b60008060408385031215612ce557600080fd5b8235612cf081612bd7565b946020939093013593505050565b600080600060608486031215612d1357600080fd5b8335612d1e81612bd7565b92506020840135612d2e81612bd7565b9150604084013560038110612d4257600080fd5b809150509250925092565b600080600060608486031215612d6257600080fd5b8335612d6d81612bd7565b92506020840135612d7d81612bd7565b9150604084013563ffffffff81168114612d4257600080fd5b60008060408385031215612da957600080fd5b823591506020830135612c1a81612bd7565b600080600060608486031215612dd057600080fd5b8335612ddb81612bd7565b92506020840135612deb81612bd7565b91506040840135612d4281612bd7565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612e3357634e487b7160e01b600052602160045260246000fd5b91905290565b60008083601f840112612e4b57600080fd5b5081356001600160401b03811115612e6257600080fd5b602083019150836020828501011115612e7a57600080fd5b9250929050565b600080600060408486031215612e9657600080fd5b8335612ea181612bd7565b925060208401356001600160401b03811115612ebc57600080fd5b612ec886828701612e39565b9497909650939450505050565b60008060008060608587031215612eeb57600080fd5b8435612ef681612bd7565b93506020850135925060408501356001600160401b03811115612f1857600080fd5b612f2487828801612e39565b95989497509550505050565b60008060208385031215612f4357600080fd5b82356001600160401b03811115612f5957600080fd5b8301601f81018513612f6a57600080fd5b80356001600160401b03811115612f8057600080fd5b8560208260051b8401011115612f9557600080fd5b6020919091019590945092505050565b60005b83811015612fc0578181015183820152602001612fa8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561303d57603f198786030184528151805180875261301a816020890160208501612fa5565b601f01601f19169590950160209081019550938401939190910190600101612ff1565b50929695505050505050565b60006020828403121561305b57600080fd5b5035919050565b60006020828403121561307457600080fd5b8151610ad481612bd7565b60006020828403121561309157600080fd5b81518015158114610ad457600080fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610ad757610ad76130a1565b80820180821115610ad757610ad76130a1565b81810381811115610ad757610ad76130a1565b60006020828403121561310657600080fd5b5051919050565b60008261312a57634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561319c5761319c61315e565b604052919050565b600080604083850312156131b757600080fd5b823560ff811681146131c857600080fd5b915060208301356001600160401b038111156131e357600080fd5b8301601f810185136131f457600080fd5b80356001600160401b0381111561320d5761320d61315e565b613220601f8201601f1916602001613174565b81815286602083850101111561323557600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000602082840312801561326857600080fd5b50604051602081016001600160401b038111828210171561328b5761328b61315e565b604052825161329981612bd7565b81529392505050565b600060408284031280156132b557600080fd5b50604080519081016001600160401b03811182821017156132d8576132d861315e565b60405282516132e681612bd7565b815260208301516132f681612bd7565b60208201529392505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261332f57600080fd5b8301803591506001600160401b0382111561334957600080fd5b602001915036819003821315612e7a57600080fd5b82848237600083820160008152835161337b818360208801612fa5565b0195945050505050565b60008251613397818460208701612fa5565b919091019291505056fea264697066735822122038ad83d20c219353421029f1ad8c4f7667d5f0e86af1579c64603bb56827d86064736f6c634300081b00330000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e608410000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","networkInteractionId":1,"nonce":286,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4889646478"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x18975e149bf31183f4fc8afd92f745278a749a23ff0f45a78e3cb70f4382ab36"},"type":"TRANSACTION_SEND"} +{"artifactId":"PaymentsEscrow#PaymentsEscrow","constructorArgs":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841",10000,10000],"contractName":"PaymentsEscrow","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"PaymentsEscrow#PaymentsEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"PaymentsEscrow#PaymentsEscrow","networkInteraction":{"data":"0x61020060405234801561001157600080fd5b506040516120c73803806120c78339810160408190526100309161046b565b826001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b2906103a1565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e5906103a1565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e906103a1565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b6020820152610158906103a1565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b6020820152610190906103a1565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb906103a1565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b6020820152610209906103a1565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b6020820152610245906103a1565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a906103a1565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450816276a7008082111561035c57604051635c0f65a160e01b815260048101929092526024820152604401610071565b508190506276a7008082111561038e57604051635c0f65a160e01b815260048101929092526024820152604401610071565b50506101c0919091526101e05250610510565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103dc91815260200190565b602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d91906104a0565b9050826001600160a01b0382166104485760405163218f5add60e11b815260040161007191906104c2565b5092915050565b80516001600160a01b038116811461046657600080fd5b919050565b60008060006060848603121561048057600080fd5b6104898461044f565b602085015160409095015190969495509392505050565b6000602082840312156104b257600080fd5b6104bb8261044f565b9392505050565b602081526000825180602084015260005b818110156104f057602081860181015160408684010152016104d3565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051611ad26105f5600039600081816101e00152610abb015260008181610193015261039d01526000505060005050600050506000505060005050600081816102fa0152818161041601528181610589015281816106380152818161076e0152818161094901528181610b2d01528181610d71015261131b01526000505060008181610fa6015261104e015260005050600081816108da01528181610eea01528181610f77015281816110c401526114130152611ad26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b00330000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e6084100000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002710","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"PaymentsEscrow#PaymentsEscrow","networkInteractionId":1,"nonce":287,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4889646478"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0xcf1c5d16df8a1c2f970bf187c099a274b0c874fd4df369a1083f2cde2a1f916a"},"type":"TRANSACTION_SEND"} +{"artifactId":"PaymentsEscrow#PaymentsEscrow_Instance","contractAddress":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","contractName":"PaymentsEscrow","dependencies":["HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow"],"futureId":"PaymentsEscrow#PaymentsEscrow_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"TAPCollector#TAPCollector","constructorArgs":["TAPCollector","1","0x9746Fb649B0AD9BA77201e9bf4e864B852e60841"],"contractName":"TAPCollector","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"TAPCollector#TAPCollector","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"TAPCollector#TAPCollector","networkInteraction":{"data":"0x6102a060405234801561001157600080fd5b506040516119ae3803806119ae833981016040819052610030916105d9565b80838361003e8260006103db565b6101205261004d8160016103db565b61014052815160208084019190912060e052815190820120610100524660a0526100da60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c0526001600160a01b03811661012c5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101e05260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526101649061040e565b6001600160a01b0316610160526040805180820190915260078152665374616b696e6760c81b60208201526101989061040e565b6001600160a01b03166101805260408051808201909152600d81526c47726170685061796d656e747360981b60208201526101d29061040e565b6001600160a01b03166101a05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261020d9061040e565b6001600160a01b03166101c05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b60208201526102469061040e565b6001600160a01b03166102005260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526102819061040e565b6001600160a01b0316610220526040805180820190915260118152704772617068546f6b656e4761746577617960781b60208201526102bf9061040e565b6001600160a01b03166102405260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b60208201526102fb9061040e565b6001600160a01b03166102605260408051808201909152600881526721bab930ba34b7b760c11b60208201526103309061040e565b6001600160a01b039081166102808190526101e05161018051610160516101a0516101c0516102005161022051610240516102605160408051968c168752948b166020870152928a1685850152908916606085015288166080840152871660a083015260c0820195909552935192851694918216939116917fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a439181900360e00190a45050505061081e565b60006020835110156103f7576103f0836104bc565b9050610408565b8161040284826106db565b5060ff90505b92915050565b6000806101e0516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161044991815260200190565b602060405180830381865afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a9190610799565b9050826001600160a01b0382166104b55760405163218f5add60e11b815260040161012391906107e7565b5092915050565b600080829050601f815111156104e7578260405163305a27a960e01b815260040161012391906107e7565b80516104f2826107fa565b179392505050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561052b578181015183820152602001610513565b50506000910152565b600082601f83011261054557600080fd5b81516001600160401b0381111561055e5761055e6104fa565b604051601f8201601f19908116603f011681016001600160401b038111828210171561058c5761058c6104fa565b6040528181528382016020018510156105a457600080fd5b6105b5826020830160208701610510565b949350505050565b80516001600160a01b03811681146105d457600080fd5b919050565b6000806000606084860312156105ee57600080fd5b83516001600160401b0381111561060457600080fd5b61061086828701610534565b602086015190945090506001600160401b0381111561062e57600080fd5b61063a86828701610534565b925050610649604085016105bd565b90509250925092565b600181811c9082168061066657607f821691505b60208210810361068657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156106d657806000526020600020601f840160051c810160208510156106b35750805b601f840160051c820191505b818110156106d357600081556001016106bf565b50505b505050565b81516001600160401b038111156106f4576106f46104fa565b610708816107028454610652565b8461068c565b6020601f82116001811461073c57600083156107245750848201515b600019600385901b1c1916600184901b1784556106d3565b600084815260208120601f198516915b8281101561076c578785015182556020948501946001909201910161074c565b508482101561078a5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6000602082840312156107ab57600080fd5b6107b4826105bd565b9392505050565b600081518084526107d3816020860160208601610510565b601f01601f19169290920160200192915050565b6020815260006107b460208301846107bb565b805160208083015191908110156106865760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516110e36108cb600039600050506000505060005050600050506000505060005050600061024f0152600050506000505060005050600061049201526000610460015260006108940152600061086c015260006107c7015260006107f10152600061081b01526110e36000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631ef518f21461005c5780637f07d2831461008c57806384b0196e146100ad5780638821603c146100c8578063cfdb35bd146100db575b600080fd5b61006f61006a3660046109dc565b61010c565b6040516001600160a01b0390911681526020015b60405180910390f35b61009f61009a366004610b23565b610125565b604051908152602001610083565b6100b5610372565b6040516100839796959493929190610bc6565b61009f6100d6366004610c5e565b6103b8565b61009f6100e9366004610cb0565b600260209081526000938452604080852082529284528284209052825290205481565b600061011f61011a83610db8565b6103cb565b92915050565b60008060008380602001905181019061013e9190610e75565b815151919350915033906001600160a01b0381168214610189576040516347666ba360e11b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b50508151516000610199846103cb565b84516020808201516060909201516001600160a01b038087166000908152600284526040808220838716835285528082209287168252919093529091205492935090916001600160801b03909116908181808211610213576040516308e467d960e31b815260048101929092526024820152604401610180565b50600090506102228284610fb1565b9050600061023082896103f2565b905081156102f3576040516343edff4160e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906387dbfe829061028e908f908a908a9088908e908990600401610fda565b600060405180830381600087803b1580156102a857600080fd5b505af11580156102bc573d6000803e3d6000fd5b5050506001600160a01b0380891660009081526002602090815260408083208a851684528252808320938b16835292905220859055505b866001600160a01b0316866001600160a01b03168d600281111561031957610319610fc4565b604080516001600160a01b038a168152602081018790529081018590527ffadd34108e3c00b000a046b272ee080bb1755b91078c0ef5200c0b7da6132bd19060600160405180910390a4509a9950505050505050505050565b600060608060008060006060610386610459565b61038e61048b565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b600061011f6103c68361102e565b6104b8565b6000806103db83600001516104b8565b90506103eb81846020015161056f565b9392505050565b600061040183620f4240101590565b80610414575061041482620f4240101590565b8383909161043e5760405163768bf0eb60e11b815260048101929092526024820152604401610180565b50620f4240905061044f838561103a565b6103eb9190611051565b60606104867f00000000000000000000000000000000000000000000000000000000000000006000610599565b905090565b60606104867f00000000000000000000000000000000000000000000000000000000000000006001610599565b600061011f7fe502a96d6aaed328ceacc76a5f627b9823162f5a205dab5a702b40073a6778428360000151846020015185604001518660600151876080015180519060200120604051602001610554969594939291909586526001600160a01b0394851660208701529290931660408501526001600160401b031660608401526001600160801b0391909116608083015260a082015260c00190565b60405160208183030381529060405280519060200120610644565b60008060008061057f8686610671565b92509250925061058f82826106be565b5090949350505050565b606060ff83146105b3576105ac8361077b565b905061011f565b8180546105bf90611073565b80601f01602080910402602001604051908101604052809291908181526020018280546105eb90611073565b80156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b5050505050905061011f565b600061011f6106516107ba565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600083516041036106ab5760208401516040850151606086015160001a61069d888285856108e5565b9550955095505050506106b7565b50508151600091506002905b9250925092565b60008260038111156106d2576106d2610fc4565b036106db575050565b60018260038111156106ef576106ef610fc4565b0361070d5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561072157610721610fc4565b036107425760405163fce698f760e01b815260048101829052602401610180565b600382600381111561075657610756610fc4565b03610777576040516335e2f38360e21b815260048101829052602401610180565b5050565b60606000610788836109b4565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561081357507f000000000000000000000000000000000000000000000000000000000000000046145b1561083d57507f000000000000000000000000000000000000000000000000000000000000000090565b610486604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561092057506000915060039050826109aa565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610974573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109a0575060009250600191508290506109aa565b9250600091508190505b9450945094915050565b600060ff8216601f81111561011f57604051632cd44ac360e21b815260040160405180910390fd5b6000602082840312156109ee57600080fd5b81356001600160401b03811115610a0457600080fd5b8201604081850312156103eb57600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610a4e57610a4e610a16565b60405290565b604080519081016001600160401b0381118282101715610a4e57610a4e610a16565b604051601f8201601f191681016001600160401b0381118282101715610a9e57610a9e610a16565b604052919050565b60006001600160401b03821115610abf57610abf610a16565b50601f01601f191660200190565b600082601f830112610ade57600080fd5b8135610af1610aec82610aa6565b610a76565b818152846020838601011115610b0657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215610b3657600080fd5b823560038110610b4557600080fd5b915060208301356001600160401b03811115610b6057600080fd5b610b6c85828601610acd565b9150509250929050565b60005b83811015610b91578181015183820152602001610b79565b50506000910152565b60008151808452610bb2816020860160208601610b76565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e060208201526000610be560e0830189610b9a565b8281036040840152610bf78189610b9a565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b81811015610c4d578351835260209384019390920191600101610c2f565b50909b9a5050505050505050505050565b600060208284031215610c7057600080fd5b81356001600160401b03811115610c8657600080fd5b820160a081850312156103eb57600080fd5b6001600160a01b0381168114610cad57600080fd5b50565b600080600060608486031215610cc557600080fd5b8335610cd081610c98565b92506020840135610ce081610c98565b91506040840135610cf081610c98565b809150509250925092565b6001600160401b0381168114610cad57600080fd5b6001600160801b0381168114610cad57600080fd5b600060a08284031215610d3757600080fd5b610d3f610a2c565b90508135610d4c81610c98565b81526020820135610d5c81610c98565b60208201526040820135610d6f81610cfb565b60408201526060820135610d8281610d10565b606082015260808201356001600160401b03811115610da057600080fd5b610dac84828501610acd565b60808301525092915050565b600060408236031215610dca57600080fd5b610dd2610a54565b82356001600160401b03811115610de857600080fd5b610df436828601610d25565b82525060208301356001600160401b03811115610e1057600080fd5b610e1c36828601610acd565b60208301525092915050565b600082601f830112610e3957600080fd5b8151610e47610aec82610aa6565b818152846020838601011115610e5c57600080fd5b610e6d826020830160208701610b76565b949350505050565b60008060408385031215610e8857600080fd5b82516001600160401b03811115610e9e57600080fd5b830160408186031215610eb057600080fd5b610eb8610a54565b81516001600160401b03811115610ece57600080fd5b820160a08188031215610ee057600080fd5b610ee8610a2c565b8151610ef381610c98565b81526020820151610f0381610c98565b60208201526040820151610f1681610cfb565b60408201526060820151610f2981610d10565b606082015260808201516001600160401b03811115610f4757600080fd5b610f5389828501610e28565b60808301525082525060208201516001600160401b03811115610f7557600080fd5b610f8187828501610e28565b602083810191909152959095015190969095509350505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011f5761011f610f9b565b634e487b7160e01b600052602160045260246000fd5b60c0810160038810610ffc57634e487b7160e01b600052602160045260246000fd5b9681526001600160a01b03958616602082015293851660408501526060840192909252909216608082015260a0015290565b600061011f3683610d25565b808202811582820484141761011f5761011f610f9b565b60008261106e57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061108757607f821691505b6020821081036110a757634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212204ea11b7f590e7303a0b1850b4cd59148c357bb48498bdb2606c6e97c057012e264736f6c634300081b0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841000000000000000000000000000000000000000000000000000000000000000c544150436f6c6c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"TAPCollector#TAPCollector","networkInteractionId":1,"nonce":288,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4780551768"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x07ca2606b6b23a6d6a2c7bf5c8c23c0f38a8bed5e0855dc2b6a958927f33525e"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphPayments#GraphPayments","hash":"0xfc719b86c2b331de4379e5cb9becd1543e98fdec066458bc4c99de313e15c47c","networkInteractionId":1,"receipt":{"blockHash":"0x207188bd9996c6ec335ecbe34b12197408769971066826372a2ca124fe099a4a","blockNumber":6722929,"contractAddress":"0x0E0e9AC171562b6d6141f69075DEd1E3922930B7","logs":[{"address":"0x0E0e9AC171562b6d6141f69075DEd1E3922930B7","data":"0x0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d90000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df5100000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab","logIndex":169,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f205","0x000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"]},{"address":"0x0E0e9AC171562b6d6141f69075DEd1E3922930B7","data":"0x000000000000000000000000000000000000000000000000ffffffffffffffff","logIndex":170,"topics":["0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphPayments#GraphPayments","result":{"address":"0x0E0e9AC171562b6d6141f69075DEd1E3922930B7","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","hash":"0x18975e149bf31183f4fc8afd92f745278a749a23ff0f45a78e3cb70f4382ab36","networkInteractionId":1,"receipt":{"blockHash":"0x207188bd9996c6ec335ecbe34b12197408769971066826372a2ca124fe099a4a","blockNumber":6722929,"contractAddress":"0xeB436D1CF0d6EabC759EB3bCd96BdBA4cD208eb3","logs":[{"address":"0xeB436D1CF0d6EabC759EB3bCd96BdBA4cD208eb3","data":"0x0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d90000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df5100000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab","logIndex":173,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f205","0x000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","result":{"address":"0xeB436D1CF0d6EabC759EB3bCd96BdBA4cD208eb3","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"PaymentsEscrow#PaymentsEscrow","hash":"0xcf1c5d16df8a1c2f970bf187c099a274b0c874fd4df369a1083f2cde2a1f916a","networkInteractionId":1,"receipt":{"blockHash":"0x207188bd9996c6ec335ecbe34b12197408769971066826372a2ca124fe099a4a","blockNumber":6722929,"contractAddress":"0x834f7Fd38818dF6d79265e0BBb56A06168356231","logs":[{"address":"0x834f7Fd38818dF6d79265e0BBb56A06168356231","data":"0x0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d90000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df5100000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab","logIndex":188,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f205","0x000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"PaymentsEscrow#PaymentsEscrow","result":{"address":"0x834f7Fd38818dF6d79265e0BBb56A06168356231","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"TAPCollector#TAPCollector","hash":"0x07ca2606b6b23a6d6a2c7bf5c8c23c0f38a8bed5e0855dc2b6a958927f33525e","networkInteractionId":1,"receipt":{"blockHash":"0x207188bd9996c6ec335ecbe34b12197408769971066826372a2ca124fe099a4a","blockNumber":6722929,"contractAddress":"0xfd24C169Cb89c448aaeB570507aAF77ff9277E4f","logs":[{"address":"0xfd24C169Cb89c448aaeB570507aAF77ff9277E4f","data":"0x0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d90000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df5100000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab","logIndex":201,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f205","0x000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"TAPCollector#TAPCollector","result":{"address":"0xfd24C169Cb89c448aaeB570507aAF77ff9277E4f","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":[],"artifactId":"GraphPayments#GraphPayments","dependencies":["GraphPayments#GraphPayments"],"functionName":"initialize","futureId":"GraphPayments#encodeFunctionCall(GraphPayments#GraphPayments.initialize)","result":"0x8129fc1c","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonStaking#HorizonStaking","constructorArgs":["0x9746Fb649B0AD9BA77201e9bf4e864B852e60841","0xeB436D1CF0d6EabC759EB3bCd96BdBA4cD208eb3","0x0000000000000000000000000000000000000000"],"contractName":"HorizonStaking","dependencies":["Controller#Controller","HorizonStakingExtension#HorizonStakingExtension","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","futureId":"HorizonStaking#HorizonStaking","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStaking#HorizonStaking","networkInteraction":{"data":"0x61020060405234801561001157600080fd5b50604051615b2c380380615b2c8339810160408190526100309161041b565b828181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610351565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610351565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610351565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610351565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610351565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610351565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610351565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610351565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610351565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b039081166101c052929092166101e052506104ce915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038c91815260200190565b602060405180830381865afa1580156103a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cd919061045e565b9050826001600160a01b0382166103f85760405163218f5add60e11b81526004016100749190610480565b5092915050565b80516001600160a01b038116811461041657600080fd5b919050565b60008060006060848603121561043057600080fd5b610439846103ff565b9250610447602085016103ff565b9150610455604085016103ff565b90509250925092565b60006020828403121561047057600080fd5b610479826103ff565b9392505050565b602081526000825180602084015260005b818110156104ae5760208186018101516040868401015201610491565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516155836105a960003960006102fb015260008181610dbf015281816115b60152818161166801528181612f5401528181613e120152614172015260005050600050506000505060005050600050506000612f0d015260005050600050506000505060008181610d89015281816117cd015281816125b2015281816128c80152818161295f01528181612ac00152818161380b015281816139cb01528181613d88015261401e01526155836000f3fe6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b00330000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841000000000000000000000000eb436d1cf0d6eabc759eb3bcd96bdba4cd208eb30000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStaking#HorizonStaking","networkInteractionId":1,"nonce":289,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"5078891980"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"82158962"}},"hash":"0x7d9698bd962a3dfddfebcd40600d3d1758b2d4a87ac31b85eee67578df1a46cd"},"type":"TRANSACTION_SEND"} +{"args":[],"artifactId":"PaymentsEscrow#PaymentsEscrow","dependencies":["PaymentsEscrow#PaymentsEscrow"],"functionName":"initialize","futureId":"PaymentsEscrow#encodeFunctionCall(PaymentsEscrow#PaymentsEscrow.initialize)","result":"0x8129fc1c","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"futureId":"HorizonStaking#HorizonStaking","hash":"0x7d9698bd962a3dfddfebcd40600d3d1758b2d4a87ac31b85eee67578df1a46cd","networkInteractionId":1,"receipt":{"blockHash":"0xdd671f6e06f87a90cf31aa333dcff7fcc8ad47c08cf8834468f671df35013288","blockNumber":6722935,"contractAddress":"0x4C6301489267EA82BeDA87d4dabc50A210aBa275","logs":[{"address":"0x4C6301489267EA82BeDA87d4dabc50A210aBa275","data":"0x0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d90000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53000000000000000000000000c37fcccac63cc5eece1546ce4965651991b74fea000000000000000000000000cab63af715010d12da2128777abb2103f9a0ef8f000000000000000000000000b0f7e9e2cecd3e93373dc3979f8108e4c595df5100000000000000000000000086e0221dbe437a67120bdbb8c53847fb4d756416000000000000000000000000ec2ed45a73bd2a324739691eaf425add66918fab","logIndex":70,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x000000000000000000000000ec385b1c7e34e47a71e1cb326d172fdf2207f205","0x000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","0x0000000000000000000000009746fb649b0ad9ba77201e9bf4e864b852e60841"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStaking#HorizonStaking","result":{"address":"0x4C6301489267EA82BeDA87d4dabc50A210aBa275","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x5C72b84F619399087Df1e4b686050A5F336126D9","0x0E0e9AC171562b6d6141f69075DEd1E3922930B7","0x8129fc1c"],"artifactId":"HorizonProxies#ProxyAdmin_GraphPayments","contractAddress":"0xaBE1e45c636a27aD02f0022e0AB32BF350702Df1","dependencies":["HorizonProxies#ProxyAdmin_GraphPayments","HorizonProxies#TransparentUpgradeableProxy_GraphPayments","GraphPayments#GraphPayments","GraphPayments#encodeFunctionCall(GraphPayments#GraphPayments.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"upgradeAndCall","futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","networkInteraction":{"data":"0x9623609d0000000000000000000000005c72b84f619399087df1e4b686050a5f336126d90000000000000000000000000e0e9ac171562b6d6141f69075ded1e3922930b7000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000","id":1,"to":"0xaBE1e45c636a27aD02f0022e0AB32BF350702Df1","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","networkInteractionId":1,"nonce":290,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4585008632"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"80053516"}},"hash":"0x277defd9bf19db0c341d8d7f061abd935d15782f55ef3743718ec97a0617eecc"},"type":"TRANSACTION_SEND"} +{"args":["0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","0x4C6301489267EA82BeDA87d4dabc50A210aBa275"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","HorizonProxies#GraphProxy_HorizonStaking","HorizonStaking#HorizonStaking"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"upgrade","futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","networkInteraction":{"data":"0x99a88ec4000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a20000000000000000000000004c6301489267ea82beda87d4dabc50a210aba275","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","networkInteractionId":1,"nonce":291,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4585008632"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"80053516"}},"hash":"0x2034b2e1eb795f3130b28bd62266fe4229d03458639a7b185b830fb5d2723cc9"},"type":"TRANSACTION_SEND"} +{"args":["0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","0x834f7Fd38818dF6d79265e0BBb56A06168356231","0x8129fc1c"],"artifactId":"HorizonProxies#ProxyAdmin_PaymentsEscrow","contractAddress":"0x9fa225C2D4Cf40c8B0100Af7dacb8bCf84D822d0","dependencies":["HorizonProxies#ProxyAdmin_PaymentsEscrow","HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","PaymentsEscrow#PaymentsEscrow","PaymentsEscrow#encodeFunctionCall(PaymentsEscrow#PaymentsEscrow.initialize)"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"upgradeAndCall","futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","networkInteraction":{"data":"0x9623609d0000000000000000000000009e0730ef2971aa5a9fea13be01a7cbfdbf4b4c53000000000000000000000000834f7fd38818df6d79265e0bbb56a06168356231000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x9fa225C2D4Cf40c8B0100Af7dacb8bCf84D822d0","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","networkInteractionId":1,"nonce":292,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4587553518"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"80053516"}},"hash":"0x56a3ff9780ee42e491e8c3399c9e4730d2b921984799f8702471e67e91bc5b1e"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","hash":"0x277defd9bf19db0c341d8d7f061abd935d15782f55ef3743718ec97a0617eecc","networkInteractionId":1,"receipt":{"blockHash":"0x17722ef41c8b56c97813609053b9018a53dbcc126fe2b363affba47957099523","blockNumber":6722940,"logs":[{"address":"0x5C72b84F619399087Df1e4b686050A5F336126D9","data":"0x","logIndex":90,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x0000000000000000000000000e0e9ac171562b6d6141f69075ded1e3922930b7"]},{"address":"0x5C72b84F619399087Df1e4b686050A5F336126D9","data":"0x0000000000000000000000000000000000000000000000000000000000000001","logIndex":91,"topics":["0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","hash":"0x2034b2e1eb795f3130b28bd62266fe4229d03458639a7b185b830fb5d2723cc9","networkInteractionId":1,"receipt":{"blockHash":"0xbc6a7f66d0e38e5410db6f0654fea5a7ed8e9633d78f2a12e33e40a76eaa533c","blockNumber":6722941,"logs":[{"address":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","data":"0x","logIndex":88,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000004c6301489267ea82beda87d4dabc50a210aba275"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","hash":"0x56a3ff9780ee42e491e8c3399c9e4730d2b921984799f8702471e67e91bc5b1e","networkInteractionId":1,"receipt":{"blockHash":"0xbc6a7f66d0e38e5410db6f0654fea5a7ed8e9633d78f2a12e33e40a76eaa533c","blockNumber":6722941,"logs":[{"address":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","data":"0x","logIndex":89,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x000000000000000000000000834f7fd38818df6d79265e0bbb56a06168356231"]},{"address":"0x9E0730ef2971AA5a9FEA13be01a7cbFDbf4b4c53","data":"0x0000000000000000000000000000000000000000000000000000000000000001","logIndex":90,"topics":["0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x4C6301489267EA82BeDA87d4dabc50A210aBa275","0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","dependencies":["GraphProxyAdmin#GraphProxyAdmin","HorizonStaking#HorizonStaking","HorizonProxies#GraphProxy_HorizonStaking","HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade"],"from":"0x559081d91f5ff43dfe51a07c216f8e6893805b35","functionName":"acceptProxy","futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","networkInteraction":{"data":"0xeb451a020000000000000000000000004c6301489267ea82beda87d4dabc50a210aba275000000000000000000000000563e880ec5a760fd6bd0deb2a035dffc71dbb8a2","id":1,"to":"0x86e0221dBe437a67120BdBB8c53847Fb4D756416","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","networkInteractionId":1,"nonce":293,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"4389578713"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"71782375"}},"hash":"0x1e5c4a43e253faa884a1d9f0f3094df39c64d47073a9cf49bd21f0408c4d93d0"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","hash":"0x1e5c4a43e253faa884a1d9f0f3094df39c64d47073a9cf49bd21f0408c4d93d0","networkInteractionId":1,"receipt":{"blockHash":"0x6b48d4468568bb9f70df0ec66968790f3c8df8a8d975c3b8ca3473112538d36e","blockNumber":6722946,"logs":[{"address":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","data":"0x","logIndex":183,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000004c6301489267ea82beda87d4dabc50a210aba275"]},{"address":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","data":"0x","logIndex":184,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000004c6301489267ea82beda87d4dabc50a210aba275","0x0000000000000000000000000000000000000000000000000000000000000000"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonStaking#HorizonStaking_Instance","contractAddress":"0x563E880Ec5A760FD6BD0dEB2a035dFfc71DBB8a2","contractName":"HorizonStaking","dependencies":["HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","HorizonProxies#GraphProxy_HorizonStaking"],"futureId":"HorizonStaking#HorizonStaking_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow.json new file mode 100644 index 000000000..3e87653d9 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow.json @@ -0,0 +1,159 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeEscrow", + "sourceName": "contracts/gateway/BridgeEscrow.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "approveAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "revokeAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051610c376101696000398061071f5250806106f65250806106cd528061089e5250806106a452508061067b5250806106525250806106295250610c376000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow_Instance.json new file mode 100644 index 000000000..3e87653d9 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#BridgeEscrow_Instance.json @@ -0,0 +1,159 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeEscrow", + "sourceName": "contracts/gateway/BridgeEscrow.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "approveAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + } + ], + "name": "revokeAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051610c376101696000398061071f5250806106f65250806106cd528061089e5250806106a452508061067b5250806106525250806106295250610c376000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#GraphProxy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/BridgeEscrow#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/Controller#Controller.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/Controller#Controller.json new file mode 100644 index 000000000..c74445ff4 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/Controller#Controller.json @@ -0,0 +1,349 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Controller", + "sourceName": "contracts/governance/Controller.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PartialPauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "SetContractProxy", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + } + ], + "name": "getContractProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPausePartialTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPauseTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "partialPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_contractAddress", + "type": "address" + } + ], + "name": "setContractProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_toPause", + "type": "bool" + } + ], + "name": "setPartialPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPauseGuardian", + "type": "address" + } + ], + "name": "setPauseGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_toPause", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + } + ], + "name": "unsetContractProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "updateController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506100243361003360201b6109b21760201c565b61002e6001610055565b6100e7565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff1615158115151415610075576100e4565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff910416156100a157426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a15b50565b610ba0806100f66000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80636cda3798116100a2578063e0e9929211610071578063e0e9929214610215578063e3056a3414610241578063eb5dd94f14610249578063f2fde38b14610275578063f7641a5e1461029b5761010b565b80636cda3798146101ce57806379ba5097146101e85780639181df9c146101f057806391b4ded91461020d5761010b565b806348bde20c116100de57806348bde20c146101795780634fc07d751461019f57806356371bd8146101a75780635c975abb146101c65761010b565b80630c340a241461011057806316c38b3c1461013457806324a3d622146101555780632e292fc71461015d575b600080fd5b6101186102b8565b604080516001600160a01b039092168252519081900360200190f35b6101536004803603602081101561014a57600080fd5b503515156102c7565b005b610118610331565b610165610340565b604080519115158252519081900360200190f35b6101536004803603602081101561018f57600080fd5b50356001600160a01b0316610350565b61011861040c565b610153600480360360208110156101bd57600080fd5b5035151561041b565b610165610482565b6101d6610492565b60408051918252519081900360200190f35b610153610498565b6101536004803603602081101561020657600080fd5b50356105a6565b6101d6610651565b6101536004803603604081101561022b57600080fd5b50803590602001356001600160a01b0316610657565b61011861076e565b6101536004803603604081101561025f57600080fd5b50803590602001356001600160a01b031661077d565b6101536004803603602081101561028b57600080fd5b50356001600160a01b0316610899565b610118600480360360208110156102b157600080fd5b5035610997565b6000546001600160a01b031681565b6000546001600160a01b03163314806102ea57506004546001600160a01b031633145b6103255760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e816109d4565b50565b6004546001600160a01b031681565b600154600160a01b900460ff1690565b6000546001600160a01b031633146103a8576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610403576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b61032e81610a65565b6000546001600160a01b031690565b6000546001600160a01b031633148061043e57506004546001600160a01b031633145b6104795760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e81610ab7565b600154600160a81b900460ff1690565b60025481565b6001546001600160a01b031680158015906104bb5750336001600160a01b038216145b61050c576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b031916905580519283525183927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a250565b60035481565b6000546001600160a01b031633146106af576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661070a576040805162461bcd60e51b815260206004820152601c60248201527f436f6e74726163742061646472657373206d7573742062652073657400000000604482015290519081900360640190fd5b60008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a25050565b6001546001600160a01b031681565b6000546001600160a01b031633146107d5576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610829576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b6000828152600560205260408082205481516392eefe9b60e01b81526001600160a01b038581166004830152925192909116926392eefe9b9260248084019382900301818387803b15801561087d57600080fd5b505af1158015610891573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146108f1576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610943576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000908152600560205260409020546001600160a01b031690565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff16151581151514156109f45761032e565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615610a2057426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b600160149054906101000a900460ff1615158115151415610ad75761032e565b6001805460ff60a01b1916600160a01b8315158102919091179182905560ff91041615610b0357426002555b60015460408051600160a01b90920460ff1615158252517f511b770d1b1dc5cbd412a5017f55cbb2295b826385e5f46c1de2b6ebeb44ae02916020908290030190a15056fe4f6e6c7920476f7665726e6f72206f7220477561726469616e2063616e2063616c6ca2646970667358221220c742dbbf8f38fda928d26053c584788bb7d7b003131594b9e14f1381ebbdbb3064736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80636cda3798116100a2578063e0e9929211610071578063e0e9929214610215578063e3056a3414610241578063eb5dd94f14610249578063f2fde38b14610275578063f7641a5e1461029b5761010b565b80636cda3798146101ce57806379ba5097146101e85780639181df9c146101f057806391b4ded91461020d5761010b565b806348bde20c116100de57806348bde20c146101795780634fc07d751461019f57806356371bd8146101a75780635c975abb146101c65761010b565b80630c340a241461011057806316c38b3c1461013457806324a3d622146101555780632e292fc71461015d575b600080fd5b6101186102b8565b604080516001600160a01b039092168252519081900360200190f35b6101536004803603602081101561014a57600080fd5b503515156102c7565b005b610118610331565b610165610340565b604080519115158252519081900360200190f35b6101536004803603602081101561018f57600080fd5b50356001600160a01b0316610350565b61011861040c565b610153600480360360208110156101bd57600080fd5b5035151561041b565b610165610482565b6101d6610492565b60408051918252519081900360200190f35b610153610498565b6101536004803603602081101561020657600080fd5b50356105a6565b6101d6610651565b6101536004803603604081101561022b57600080fd5b50803590602001356001600160a01b0316610657565b61011861076e565b6101536004803603604081101561025f57600080fd5b50803590602001356001600160a01b031661077d565b6101536004803603602081101561028b57600080fd5b50356001600160a01b0316610899565b610118600480360360208110156102b157600080fd5b5035610997565b6000546001600160a01b031681565b6000546001600160a01b03163314806102ea57506004546001600160a01b031633145b6103255760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e816109d4565b50565b6004546001600160a01b031681565b600154600160a01b900460ff1690565b6000546001600160a01b031633146103a8576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610403576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b61032e81610a65565b6000546001600160a01b031690565b6000546001600160a01b031633148061043e57506004546001600160a01b031633145b6104795760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e81610ab7565b600154600160a81b900460ff1690565b60025481565b6001546001600160a01b031680158015906104bb5750336001600160a01b038216145b61050c576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b031916905580519283525183927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a250565b60035481565b6000546001600160a01b031633146106af576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661070a576040805162461bcd60e51b815260206004820152601c60248201527f436f6e74726163742061646472657373206d7573742062652073657400000000604482015290519081900360640190fd5b60008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a25050565b6001546001600160a01b031681565b6000546001600160a01b031633146107d5576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610829576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b6000828152600560205260408082205481516392eefe9b60e01b81526001600160a01b038581166004830152925192909116926392eefe9b9260248084019382900301818387803b15801561087d57600080fd5b505af1158015610891573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146108f1576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610943576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000908152600560205260409020546001600160a01b031690565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff16151581151514156109f45761032e565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615610a2057426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b600160149054906101000a900460ff1615158115151415610ad75761032e565b6001805460ff60a01b1916600160a01b8315158102919091179182905560ff91041615610b0357426002555b60015460408051600160a01b90920460ff1615158252517f511b770d1b1dc5cbd412a5017f55cbb2295b826385e5f46c1de2b6ebeb44ae02916020908290030190a15056fe4f6e6c7920476f7665726e6f72206f7220477561726469616e2063616e2063616c6ca2646970667358221220c742dbbf8f38fda928d26053c584788bb7d7b003131594b9e14f1381ebbdbb3064736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation.json new file mode 100644 index 000000000..f9d96cee6 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation.json @@ -0,0 +1,707 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2Curation", + "sourceName": "contracts/l2/curation/L2Curation.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Collected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curationTax", + "type": "uint256" + } + ], + "name": "Signalled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bondingCurve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_tokensOutMin", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTaxPercentage", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTokenMaster", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultReserveRatio", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCuratorSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_curationTaxPercentage", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isCurated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumCurationDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_signalOutMin", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "mintTaxFree", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "reserveRatio", + "type": "uint32" + }, + { + "internalType": "contract IGraphCurationToken", + "name": "gcs", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_percentage", + "type": "uint32" + } + ], + "name": "setCurationTaxPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + } + ], + "name": "setCurationTokenMaster", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "setDefaultReserveRatio", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "setMinimumCurationDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + } + ], + "name": "signalToTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalToTokensNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6101806040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea361014052613d0960e61b6101605234801561011a57600080fd5b5060805160a05160c05160e0516101005161012051610140516101605160e01c6128cc61018f60003980610c2f52508061141b52806119025250806113f25250806113c9528061180c5250806113a05280611dbf5250806113775280611ff252508061134e52508061132552506128cc6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation_Instance.json new file mode 100644 index 000000000..f9d96cee6 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#Curation_Instance.json @@ -0,0 +1,707 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2Curation", + "sourceName": "contracts/l2/curation/L2Curation.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Collected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "signal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curationTax", + "type": "uint256" + } + ], + "name": "Signalled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bondingCurve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_tokensOutMin", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTaxPercentage", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curationTokenMaster", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultReserveRatio", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCurationPoolTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curator", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getCuratorSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_curationTaxPercentage", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isCurated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumCurationDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_signalOutMin", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "mintTaxFree", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "reserveRatio", + "type": "uint32" + }, + { + "internalType": "contract IGraphCurationToken", + "name": "gcs", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_percentage", + "type": "uint32" + } + ], + "name": "setCurationTaxPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_curationTokenMaster", + "type": "address" + } + ], + "name": "setCurationTokenMaster", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "setDefaultReserveRatio", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumCurationDeposit", + "type": "uint256" + } + ], + "name": "setMinimumCurationDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_signalIn", + "type": "uint256" + } + ], + "name": "signalToTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_tokensIn", + "type": "uint256" + } + ], + "name": "tokensToSignalToTokensNoTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6101806040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea361014052613d0960e61b6101605234801561011a57600080fd5b5060805160a05160c05160e0516101005161012051610140516101605160e01c6128cc61018f60003980610c2f52508061141b52806119025250806113f25250806113c9528061180c5250806113a05280611dbf5250806113775280611ff252508061134e52508061132552506128cc6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphCurationToken.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphCurationToken.json new file mode 100644 index 000000000..b7220dcc7 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphCurationToken.json @@ -0,0 +1,414 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphCurationToken", + "sourceName": "contracts/curation/GraphCurationToken.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506114ec806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806379ba5097116100a2578063a9059cbb11610071578063a9059cbb14610352578063c4d66de81461037e578063dd62ed3e146103a4578063e3056a34146103d2578063f2fde38b146103da57610116565b806379ba5097146102ea57806379cc6790146102f257806395d89b411461031e578063a457c2d71461032657610116565b806323b872dd116100e957806323b872dd14610216578063313ce5671461024c578063395093511461026a57806340c10f191461029657806370a08231146102c457610116565b806306fdde031461011b578063095ea7b3146101985780630c340a24146101d857806318160ddd146101fc575b600080fd5b610123610400565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015d578181015183820152602001610145565b50505050905090810190601f16801561018a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c4600480360360408110156101ae57600080fd5b506001600160a01b038135169060200135610496565b604080519115158252519081900360200190f35b6101e06104b3565b604080516001600160a01b039092168252519081900360200190f35b6102046104c2565b60408051918252519081900360200190f35b6101c46004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356104c8565b61025461054f565b6040805160ff9092168252519081900360200190f35b6101c46004803603604081101561028057600080fd5b506001600160a01b038135169060200135610558565b6102c2600480360360408110156102ac57600080fd5b506001600160a01b0381351690602001356105a6565b005b610204600480360360208110156102da57600080fd5b50356001600160a01b031661060c565b6102c2610627565b6102c26004803603604081101561030857600080fd5b506001600160a01b038135169060200135610737565b610123610799565b6101c46004803603604081101561033c57600080fd5b506001600160a01b0381351690602001356107fa565b6101c46004803603604081101561036857600080fd5b506001600160a01b038135169060200135610862565b6102c26004803603602081101561039457600080fd5b50356001600160a01b0316610876565b610204600480360360408110156103ba57600080fd5b506001600160a01b0381358116916020013516610972565b6101e061099d565b6102c2600480360360208110156103f057600080fd5b50356001600160a01b03166109ac565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b820191906000526020600020905b81548152906001019060200180831161046f57829003601f168201915b5050505050905090565b60006104aa6104a3610aaa565b8484610aae565b50600192915050565b6065546001600160a01b031681565b60355490565b60006104d5848484610b9a565b610545846104e1610aaa565b61054085604051806060016040528060288152602001611400602891396001600160a01b038a1660009081526034602052604081209061051f610aaa565b6001600160a01b031681526020810191909152604001600020549190610cf7565b610aae565b5060019392505050565b60385460ff1690565b60006104aa610565610aaa565b846105408560346000610576610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610d8e565b6065546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610def565b5050565b6001600160a01b031660009081526033602052604090205490565b6066546001600160a01b0316801580159061064a5750336001600160a01b038216145b61069b576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b606580546001600160a01b038381166001600160a01b0319808416919091179384905560668054909116905560405191811692169082907f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f90600090a36066546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6065546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610ee1565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b60006104aa610807610aaa565b84610540856040518060600160405280602581526020016114926025913960346000610831610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610cf7565b60006104aa61086f610aaa565b8484610b9a565b600054610100900460ff168061088f575061088f610fdd565b8061089d575060005460ff16155b6108d85760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015610903576000805460ff1961ff0019909116610100171660011790555b61090c82610fee565b61095d604051806040016040528060148152602001734772617068204375726174696f6e20536861726560601b8152506040518060400160405280600381526020016247435360e81b815250611010565b8015610608576000805461ff00191690555050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6066546001600160a01b031681565b6065546001600160a01b03163314610a04576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610a56576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b606680546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b038316610af35760405162461bcd60e51b815260040180806020018281038252602481526020018061146e6024913960400191505060405180910390fd5b6001600160a01b038216610b385760405162461bcd60e51b815260040180806020018281038252602281526020018061138a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610bdf5760405162461bcd60e51b81526004018080602001828103825260258152602001806114496025913960400191505060405180910390fd5b6001600160a01b038216610c245760405162461bcd60e51b81526004018080602001828103825260238152602001806113456023913960400191505060405180910390fd5b610c2f8383836110c1565b610c6c816040518060600160405280602681526020016113ac602691396001600160a01b0386166000908152603360205260409020549190610cf7565b6001600160a01b038085166000908152603360205260408082209390935590841681522054610c9b9082610d8e565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610d865760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d4b578181015183820152602001610d33565b50505050905090810190601f168015610d785780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610de8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610e4a576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610e56600083836110c1565b603554610e639082610d8e565b6035556001600160a01b038216600090815260336020526040902054610e899082610d8e565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610f265760405162461bcd60e51b81526004018080602001828103825260218152602001806114286021913960400191505060405180910390fd5b610f32826000836110c1565b610f6f81604051806060016040528060228152602001611368602291396001600160a01b0385166000908152603360205260409020549190610cf7565b6001600160a01b038316600090815260336020526040902055603554610f9590826110c6565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000610fe830611123565b15905090565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16806110295750611029610fdd565b80611037575060005460ff16155b6110725760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff1615801561109d576000805460ff1961ff0019909116610100171660011790555b6110a5611129565b6110af83836111cb565b80156110c1576000805461ff00191690555b505050565b60008282111561111d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600054610100900460ff16806111425750611142610fdd565b80611150575060005460ff16155b61118b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff161580156111b6576000805460ff1961ff0019909116610100171660011790555b80156111c8576000805461ff00191690555b50565b600054610100900460ff16806111e457506111e4610fdd565b806111f2575060005460ff16155b61122d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015611258576000805460ff1961ff0019909116610100171660011790555b825161126b9060369060208601906112a3565b50815161127f9060379060208501906112a3565b506038805460ff1916601217905580156110c1576000805461ff0019169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826112d9576000855561131f565b82601f106112f257805160ff191683800117855561131f565b8280016001018555821561131f579182015b8281111561131f578251825591602001919060010190611304565b5061132b92915061132f565b5090565b5b8082111561132b576000815560010161133056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200b687fddcd01dbad6e1d5fbd49cb041f69ed61684a12a4c26c6e37e0f5ad7c2a64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101165760003560e01c806379ba5097116100a2578063a9059cbb11610071578063a9059cbb14610352578063c4d66de81461037e578063dd62ed3e146103a4578063e3056a34146103d2578063f2fde38b146103da57610116565b806379ba5097146102ea57806379cc6790146102f257806395d89b411461031e578063a457c2d71461032657610116565b806323b872dd116100e957806323b872dd14610216578063313ce5671461024c578063395093511461026a57806340c10f191461029657806370a08231146102c457610116565b806306fdde031461011b578063095ea7b3146101985780630c340a24146101d857806318160ddd146101fc575b600080fd5b610123610400565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015d578181015183820152602001610145565b50505050905090810190601f16801561018a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c4600480360360408110156101ae57600080fd5b506001600160a01b038135169060200135610496565b604080519115158252519081900360200190f35b6101e06104b3565b604080516001600160a01b039092168252519081900360200190f35b6102046104c2565b60408051918252519081900360200190f35b6101c46004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356104c8565b61025461054f565b6040805160ff9092168252519081900360200190f35b6101c46004803603604081101561028057600080fd5b506001600160a01b038135169060200135610558565b6102c2600480360360408110156102ac57600080fd5b506001600160a01b0381351690602001356105a6565b005b610204600480360360208110156102da57600080fd5b50356001600160a01b031661060c565b6102c2610627565b6102c26004803603604081101561030857600080fd5b506001600160a01b038135169060200135610737565b610123610799565b6101c46004803603604081101561033c57600080fd5b506001600160a01b0381351690602001356107fa565b6101c46004803603604081101561036857600080fd5b506001600160a01b038135169060200135610862565b6102c26004803603602081101561039457600080fd5b50356001600160a01b0316610876565b610204600480360360408110156103ba57600080fd5b506001600160a01b0381358116916020013516610972565b6101e061099d565b6102c2600480360360208110156103f057600080fd5b50356001600160a01b03166109ac565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b820191906000526020600020905b81548152906001019060200180831161046f57829003601f168201915b5050505050905090565b60006104aa6104a3610aaa565b8484610aae565b50600192915050565b6065546001600160a01b031681565b60355490565b60006104d5848484610b9a565b610545846104e1610aaa565b61054085604051806060016040528060288152602001611400602891396001600160a01b038a1660009081526034602052604081209061051f610aaa565b6001600160a01b031681526020810191909152604001600020549190610cf7565b610aae565b5060019392505050565b60385460ff1690565b60006104aa610565610aaa565b846105408560346000610576610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610d8e565b6065546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610def565b5050565b6001600160a01b031660009081526033602052604090205490565b6066546001600160a01b0316801580159061064a5750336001600160a01b038216145b61069b576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b606580546001600160a01b038381166001600160a01b0319808416919091179384905560668054909116905560405191811692169082907f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f90600090a36066546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6065546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610ee1565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b60006104aa610807610aaa565b84610540856040518060600160405280602581526020016114926025913960346000610831610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610cf7565b60006104aa61086f610aaa565b8484610b9a565b600054610100900460ff168061088f575061088f610fdd565b8061089d575060005460ff16155b6108d85760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015610903576000805460ff1961ff0019909116610100171660011790555b61090c82610fee565b61095d604051806040016040528060148152602001734772617068204375726174696f6e20536861726560601b8152506040518060400160405280600381526020016247435360e81b815250611010565b8015610608576000805461ff00191690555050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6066546001600160a01b031681565b6065546001600160a01b03163314610a04576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610a56576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b606680546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b038316610af35760405162461bcd60e51b815260040180806020018281038252602481526020018061146e6024913960400191505060405180910390fd5b6001600160a01b038216610b385760405162461bcd60e51b815260040180806020018281038252602281526020018061138a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610bdf5760405162461bcd60e51b81526004018080602001828103825260258152602001806114496025913960400191505060405180910390fd5b6001600160a01b038216610c245760405162461bcd60e51b81526004018080602001828103825260238152602001806113456023913960400191505060405180910390fd5b610c2f8383836110c1565b610c6c816040518060600160405280602681526020016113ac602691396001600160a01b0386166000908152603360205260409020549190610cf7565b6001600160a01b038085166000908152603360205260408082209390935590841681522054610c9b9082610d8e565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610d865760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d4b578181015183820152602001610d33565b50505050905090810190601f168015610d785780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610de8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610e4a576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610e56600083836110c1565b603554610e639082610d8e565b6035556001600160a01b038216600090815260336020526040902054610e899082610d8e565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610f265760405162461bcd60e51b81526004018080602001828103825260218152602001806114286021913960400191505060405180910390fd5b610f32826000836110c1565b610f6f81604051806060016040528060228152602001611368602291396001600160a01b0385166000908152603360205260409020549190610cf7565b6001600160a01b038316600090815260336020526040902055603554610f9590826110c6565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000610fe830611123565b15905090565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16806110295750611029610fdd565b80611037575060005460ff16155b6110725760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff1615801561109d576000805460ff1961ff0019909116610100171660011790555b6110a5611129565b6110af83836111cb565b80156110c1576000805461ff00191690555b505050565b60008282111561111d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600054610100900460ff16806111425750611142610fdd565b80611150575060005460ff16155b61118b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff161580156111b6576000805460ff1961ff0019909116610100171660011790555b80156111c8576000805461ff00191690555b50565b600054610100900460ff16806111e457506111e4610fdd565b806111f2575060005460ff16155b61122d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015611258576000805460ff1961ff0019909116610100171660011790555b825161126b9060369060208601906112a3565b50815161127f9060379060208501906112a3565b506038805460ff1916601217905580156110c1576000805461ff0019169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826112d9576000855561131f565b82601f106112f257805160ff191683800117855561131f565b8280016001018555821561131f579182015b8281111561131f578251825591602001919060010190611304565b5061132b92915061132f565b5090565b5b8082111561132b576000815560010161133056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200b687fddcd01dbad6e1d5fbd49cb041f69ed61684a12a4c26c6e37e0f5ad7c2a64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphProxy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/Curation#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager.json new file mode 100644 index 000000000..cd09f36f8 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager.json @@ -0,0 +1,364 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EpochManager", + "sourceName": "contracts/epochs/EpochManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochLength", + "type": "uint256" + } + ], + "name": "EpochLengthUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "EpochRun", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlockSinceStart", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "epochsSince", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochsSinceUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isCurrentEpochRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRunEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "runEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "setEpochLength", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161103461016460003980610aac525080610a83525080610a5a525080610a31525080610a085250806109df5250806109b652506110346000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager_Instance.json new file mode 100644 index 000000000..cd09f36f8 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#EpochManager_Instance.json @@ -0,0 +1,364 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EpochManager", + "sourceName": "contracts/epochs/EpochManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochLength", + "type": "uint256" + } + ], + "name": "EpochLengthUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "EpochRun", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentEpochBlockSinceStart", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "epochsSince", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochsSinceUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isCurrentEpochRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastLengthUpdateEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRunEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "runEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "name": "setEpochLength", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161103461016460003980610aac525080610a83525080610a5a525080610a31525080610a085250806109df5250806109b652506110346000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#GraphProxy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/EpochManager#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphHorizon_Periphery#Dummy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphHorizon_Periphery#Dummy.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphHorizon_Periphery#Dummy.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments.json new file mode 100644 index 000000000..d9b94acde --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments.json @@ -0,0 +1,308 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphPayments", + "sourceName": "contracts/payments/GraphPayments.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "GraphPaymentsInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "name": "GraphPaymentsInvalidProtocolPaymentCut", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensReceiver", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDelegationPool", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensProtocol", + "type": "uint256" + } + ], + "name": "PaymentCollected", + "type": "event" + }, + { + "inputs": [], + "name": "PROTOCOL_PAYMENT_CUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101e060405234801561001157600080fd5b5060405161132f38038061132f833981016040819052610030916104ee565b816001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b290610372565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e590610372565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e90610372565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015890610372565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019090610372565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb90610372565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020990610372565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024590610372565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a90610372565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a45061033a81620f4240101590565b819061035c5760405163d3097bcb60e01b815260040161007191815260200190565b506101c081905261036b610420565b505061058a565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103ad91815260200190565b602060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ee919061051a565b9050826001600160a01b0382166104195760405163218f5add60e11b8152600401610071919061053c565b5092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156104705760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146104cf5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146104e957600080fd5b919050565b6000806040838503121561050157600080fd5b61050a836104d2565b9150602083015190509250929050565b60006020828403121561052c57600080fd5b610535826104d2565b9392505050565b602081526000825180602084015260005b8181101561056a576020818601810151604086840101520161054d565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051610d086106276000396000818160560152610104015260005050600050506000505060005050600050506000505060005050600050506000818161012e015281816102c1015261035401526000818160d5015281816102220152818161025a0152818161029201526103f50152610d086000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments_Instance.json new file mode 100644 index 000000000..d9b94acde --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphPayments#GraphPayments_Instance.json @@ -0,0 +1,308 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphPayments", + "sourceName": "contracts/payments/GraphPayments.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "GraphPaymentsInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "protocolPaymentCut", + "type": "uint256" + } + ], + "name": "GraphPaymentsInvalidProtocolPaymentCut", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensReceiver", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDelegationPool", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensProtocol", + "type": "uint256" + } + ], + "name": "PaymentCollected", + "type": "event" + }, + { + "inputs": [], + "name": "PROTOCOL_PAYMENT_CUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101e060405234801561001157600080fd5b5060405161132f38038061132f833981016040819052610030916104ee565b816001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b290610372565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e590610372565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e90610372565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015890610372565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019090610372565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb90610372565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020990610372565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024590610372565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a90610372565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a45061033a81620f4240101590565b819061035c5760405163d3097bcb60e01b815260040161007191815260200190565b506101c081905261036b610420565b505061058a565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103ad91815260200190565b602060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ee919061051a565b9050826001600160a01b0382166104195760405163218f5add60e11b8152600401610071919061053c565b5092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156104705760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146104cf5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146104e957600080fd5b919050565b6000806040838503121561050157600080fd5b61050a836104d2565b9150602083015190509250929050565b60006020828403121561052c57600080fd5b610535826104d2565b9392505050565b602081526000825180602084015260005b8181101561056a576020818601810151604086840101520161054d565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051610d086106276000396000818160560152610104015260005050600050506000505060005050600050506000505060005050600050506000818161012e015281816102c1015261035401526000818160d5015281816102220152818161025a0152818161029201526103f50152610d086000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphProxyAdmin#GraphProxyAdmin.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphProxyAdmin#GraphProxyAdmin.json new file mode 100644 index 000000000..07f0623c5 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphProxyAdmin#GraphProxyAdmin.json @@ -0,0 +1,234 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxyAdmin", + "sourceName": "contracts/upgrades/GraphProxyAdmin.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract GraphUpgradeable", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract GraphUpgradeable", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "getProxyPendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b506100243361002960201b610a0c1760201c565b61004b565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610a648061005a6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80637eff275e116100715780637eff275e146101b157806399a88ec4146101df578063e3056a341461020d578063eb451a0214610215578063f2fde38b14610243578063f3b7dead14610269576100a9565b806307ebde0e146100ae5780630c340a2414610139578063204e1c7a1461015d5780635bf410eb1461018357806379ba5097146101a9575b600080fd5b610137600480360360608110156100c457600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b50909250905061028f565b005b610141610388565b604080516001600160a01b039092168252519081900360200190f35b6101416004803603602081101561017357600080fd5b50356001600160a01b0316610397565b6101416004803603602081101561019957600080fd5b50356001600160a01b031661046a565b610137610525565b610137600480360360408110156101c757600080fd5b506001600160a01b0381358116916020013516610633565b610137600480360360408110156101f557600080fd5b506001600160a01b03813581169160200135166106f6565b61014161079d565b6101376004803603604081101561022b57600080fd5b506001600160a01b03813581169160200135166107ac565b6101376004803603602081101561025957600080fd5b50356001600160a01b0316610853565b6101416004803603602081101561027f57600080fd5b50356001600160a01b0316610951565b6000546001600160a01b031633146102e7576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b836001600160a01b0316639ce7abe58484846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b15801561036a57600080fd5b505af115801561037e573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031681565b6000806000836001600160a01b03166040518080635c60da1b60e01b8152506004019050600060405180830381855afa9150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b50915091508161044b576040805162461bcd60e51b8152602060048201526016602482015275141c9bde1e481a5b5c1b0818d85b1b0819985a5b195960521b604482015290519081900360640190fd5b80806020019051602081101561046057600080fd5b5051949350505050565b6000806000836001600160a01b0316604051808063396f7b2360e01b8152506004019050600060405180830381855afa9150503d80600081146104c9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ce565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601d60248201527f50726f78792070656e64696e67496d706c2063616c6c206661696c6564000000604482015290519081900360640190fd5b6001546001600160a01b031680158015906105485750336001600160a01b038216145b610599576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b0316331461068b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663704b6c02826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b505af11580156106ee573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461074e576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b0316633659cfe6826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6001546001600160a01b031681565b6000546001600160a01b03163314610804576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663a2594d82826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6000546001600160a01b031633146108ab576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b0381166108fd576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000806000836001600160a01b031660405180806303e1469160e61b8152506004019050600060405180830381855afa9150503d80600081146109b0576040519150601f19603f3d011682016040523d82523d6000602084013e6109b5565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601760248201527f50726f78792061646d696e2063616c6c206661696c6564000000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b039290921691909117905556fea26469706673582212208b271ee4c7625d89f662c15e90f70e142245bf56f0595043fe9af742b09d958c64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80637eff275e116100715780637eff275e146101b157806399a88ec4146101df578063e3056a341461020d578063eb451a0214610215578063f2fde38b14610243578063f3b7dead14610269576100a9565b806307ebde0e146100ae5780630c340a2414610139578063204e1c7a1461015d5780635bf410eb1461018357806379ba5097146101a9575b600080fd5b610137600480360360608110156100c457600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b50909250905061028f565b005b610141610388565b604080516001600160a01b039092168252519081900360200190f35b6101416004803603602081101561017357600080fd5b50356001600160a01b0316610397565b6101416004803603602081101561019957600080fd5b50356001600160a01b031661046a565b610137610525565b610137600480360360408110156101c757600080fd5b506001600160a01b0381358116916020013516610633565b610137600480360360408110156101f557600080fd5b506001600160a01b03813581169160200135166106f6565b61014161079d565b6101376004803603604081101561022b57600080fd5b506001600160a01b03813581169160200135166107ac565b6101376004803603602081101561025957600080fd5b50356001600160a01b0316610853565b6101416004803603602081101561027f57600080fd5b50356001600160a01b0316610951565b6000546001600160a01b031633146102e7576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b836001600160a01b0316639ce7abe58484846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b15801561036a57600080fd5b505af115801561037e573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031681565b6000806000836001600160a01b03166040518080635c60da1b60e01b8152506004019050600060405180830381855afa9150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b50915091508161044b576040805162461bcd60e51b8152602060048201526016602482015275141c9bde1e481a5b5c1b0818d85b1b0819985a5b195960521b604482015290519081900360640190fd5b80806020019051602081101561046057600080fd5b5051949350505050565b6000806000836001600160a01b0316604051808063396f7b2360e01b8152506004019050600060405180830381855afa9150503d80600081146104c9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ce565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601d60248201527f50726f78792070656e64696e67496d706c2063616c6c206661696c6564000000604482015290519081900360640190fd5b6001546001600160a01b031680158015906105485750336001600160a01b038216145b610599576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b0316331461068b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663704b6c02826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b505af11580156106ee573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461074e576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b0316633659cfe6826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6001546001600160a01b031681565b6000546001600160a01b03163314610804576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663a2594d82826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6000546001600160a01b031633146108ab576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b0381166108fd576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000806000836001600160a01b031660405180806303e1469160e61b8152506004019050600060405180830381855afa9150503d80600081146109b0576040519150601f19603f3d011682016040523d82523d6000602084013e6109b5565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601760248201527f50726f78792061646d696e2063616c6c206661696c6564000000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b039290921691909117905556fea26469706673582212208b271ee4c7625d89f662c15e90f70e142245bf56f0595043fe9af742b09d958c64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphProxy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken.json new file mode 100644 index 000000000..5889eeaf0 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken.json @@ -0,0 +1,750 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphToken", + "sourceName": "contracts/l2/token/L2GraphToken.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "name": "GatewaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "L1AddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Address", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "removeMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gw", + "type": "address" + } + ], + "name": "setGateway", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "setL1Address", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101206040527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726080527fefcec85968da792893fa503eb21730083fc6c50ed5461e56163b28335b2a5f9660a0527f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d60c0527fe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f565959160e0527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610100523480156100c657600080fd5b5060805160a05160c05160e0516101005161261e61010660003980611547525080611eae525080611e5e525080611e3d525080611e1c525061261e6000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken_Instance.json new file mode 100644 index 000000000..5889eeaf0 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphToken#GraphToken_Instance.json @@ -0,0 +1,750 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphToken", + "sourceName": "contracts/l2/token/L2GraphToken.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "BridgeMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "name": "GatewaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "L1AddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "NewPendingOwnership", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "bridgeMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Address", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingGovernor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "removeMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gw", + "type": "address" + } + ], + "name": "setGateway", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "setL1Address", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101206040527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726080527fefcec85968da792893fa503eb21730083fc6c50ed5461e56163b28335b2a5f9660a0527f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d60c0527fe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f565959160e0527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610100523480156100c657600080fd5b5060805160a05160c05160e0516101005161261e61010660003980611547525080611eae525080611e5e525080611e3d525080611e1c525061261e6000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphProxy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway.json new file mode 100644 index 000000000..a9c54a794 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway.json @@ -0,0 +1,647 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphTokenGateway", + "sourceName": "contracts/l2/gateway/L2GraphTokenGateway.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Counterpart", + "type": "address" + } + ], + "name": "L1CounterpartAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1GRT", + "type": "address" + } + ], + "name": "L1TokenAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l2Router", + "type": "address" + } + ], + "name": "L2RouterSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PartialPauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "TxToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "l2ToL1Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawalInitiated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Counterpart", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1GRT", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Router", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPausePartialTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPauseTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Counterpart", + "type": "address" + } + ], + "name": "setL1CounterpartAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1GRT", + "type": "address" + } + ], + "name": "setL1TokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Router", + "type": "address" + } + ], + "name": "setL2Router", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPauseGuardian", + "type": "address" + } + ], + "name": "setPauseGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_newPaused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161222b6101696000398061112f5250806111065250806110dd528061150a5250806110b452508061108b525080611062525080611039525061222b6000f3fe6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "deployedBytecode": "0x6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json new file mode 100644 index 000000000..a9c54a794 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/GraphTokenGateway#GraphTokenGateway_Instance.json @@ -0,0 +1,647 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "L2GraphTokenGateway", + "sourceName": "contracts/l2/gateway/L2GraphTokenGateway.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Counterpart", + "type": "address" + } + ], + "name": "L1CounterpartAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1GRT", + "type": "address" + } + ], + "name": "L1TokenAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l2Router", + "type": "address" + } + ], + "name": "L2RouterSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PartialPauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "TxToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "l2ToL1Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawalInitiated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Counterpart", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1GRT", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Router", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPausePartialTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPauseTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Counterpart", + "type": "address" + } + ], + "name": "setL1CounterpartAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1GRT", + "type": "address" + } + ], + "name": "setL1TokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Router", + "type": "address" + } + ], + "name": "setL2Router", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPauseGuardian", + "type": "address" + } + ], + "name": "setPauseGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_newPaused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161222b6101696000398061112f5250806111065250806110dd528061150a5250806110b452508061108b525080611062525080611039525061222b6000f3fe6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "deployedBytecode": "0x6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#GraphProxy_HorizonStaking.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_GraphPayments.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#OZProxyDummy_PaymentsEscrow.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json new file mode 100644 index 000000000..942e4b2e5 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_GraphPayments.json @@ -0,0 +1,132 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ProxyAdmin", + "sourceName": "contracts/proxy/transparent/ProxyAdmin.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "deployedBytecode": "0x60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json new file mode 100644 index 000000000..942e4b2e5 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#ProxyAdmin_PaymentsEscrow.json @@ -0,0 +1,132 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ProxyAdmin", + "sourceName": "contracts/proxy/transparent/ProxyAdmin.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "deployedBytecode": "0x60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#RegisteredDummy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#RegisteredDummy.json new file mode 100644 index 000000000..0d073cb30 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#RegisteredDummy.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Dummy", + "sourceName": "contracts/mocks/Dummy.sol", + "abi": [], + "bytecode": "0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json new file mode 100644 index 000000000..c7f1f49b4 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_GraphPayments.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TransparentUpgradeableProxy", + "sourceName": "contracts/proxy/transparent/TransparentUpgradeableProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "ERC1967InvalidAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "ProxyDeniedAdminAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json new file mode 100644 index 000000000..c7f1f49b4 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TransparentUpgradeableProxy", + "sourceName": "contracts/proxy/transparent/TransparentUpgradeableProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "ERC1967InvalidAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "ProxyDeniedAdminAccess", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } + ], + "bytecode": "0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking.json new file mode 100644 index 000000000..e442f237e --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking.json @@ -0,0 +1,2280 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HorizonStaking", + "sourceName": "contracts/staking/HorizonStaking.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "address", + "name": "stakingExtensionAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "subgraphDataServiceAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingCallerIsServiceProvider", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientIdleStake", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientShares", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientStakeForLegacyAllocations", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minRequired", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "HorizonStakingInvalidDelegationFeeCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidDelegationPoolState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxMaxVerifierCut", + "type": "uint32" + } + ], + "name": "HorizonStakingInvalidMaxVerifierCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidProvision", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "HorizonStakingInvalidThawingPeriod", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroShares", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingNotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingNothingThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingProvisionAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingSlippageProtection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "HorizonStakingStillThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingTooManyThawRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingTooManyTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingVerifierNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListEmptyList", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidIterations", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidZeroId", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListMaxElementsExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyController", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyGovernor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AllowedLockedVerifierSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegatedTokensWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "DelegationFeeCutSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "DelegationSlashingEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashingSkipped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "MaxThawingPeriodSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersStaged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionThawed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "ThawRequestCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + } + ], + "name": "ThawRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawRequestsFulfilled", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ThawRequestsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ThawingPeriodCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDeprovisioned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensToDelegationPoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensUndelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "VerifierTokensSent", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "acceptProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToDelegationPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSharesOut", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "deprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegatedTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.Delegation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + } + ], + "name": "getDelegationFeeCut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegationPool", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.DelegationPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getIdleStake", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProviderTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProvision", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "createdAt", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxVerifierCutPending", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriodPending", + "type": "uint64" + } + ], + "internalType": "struct IHorizonStakingTypes.Provision", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getServiceProvider", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokensStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensProvisioned", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.ServiceProvider", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "getThawRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "next", + "type": "bytes32" + } + ], + "internalType": "struct IHorizonStakingTypes.ThawRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawRequestList", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "head", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tail", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "internalType": "struct LinkedList.List", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delegationRatio", + "type": "uint32" + } + ], + "name": "getTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAllowedLockedVerifier", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAuthorized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDelegationSlashingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provisionLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "oldVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newVerifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "reprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAllowedLockedVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "setDelegationFeeCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setDelegationSlashingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "setMaxThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperatorLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "setProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensVerifier", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifierDestination", + "type": "address" + } + ], + "name": "slash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minSharesForNewProvider", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b50604051615b2c380380615b2c8339810160408190526100309161041b565b828181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610351565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610351565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610351565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610351565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610351565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610351565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610351565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610351565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610351565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b039081166101c052929092166101e052506104ce915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038c91815260200190565b602060405180830381865afa1580156103a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cd919061045e565b9050826001600160a01b0382166103f85760405163218f5add60e11b81526004016100749190610480565b5092915050565b80516001600160a01b038116811461041657600080fd5b919050565b60008060006060848603121561043057600080fd5b610439846103ff565b9250610447602085016103ff565b9150610455604085016103ff565b90509250925092565b60006020828403121561047057600080fd5b610479826103ff565b9392505050565b602081526000825180602084015260005b818110156104ae5760208186018101516040868401015201610491565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516155836105a960003960006102fb015260008181610dbf015281816115b60152818161166801528181612f5401528181613e120152614172015260005050600050506000505060005050600050506000612f0d015260005050600050506000505060008181610d89015281816117cd015281816125b2015281816128c80152818161295f01528181612ac00152818161380b015281816139cb01528181613d88015261401e01526155836000f3fe6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking_Instance.json new file mode 100644 index 000000000..e442f237e --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStaking#HorizonStaking_Instance.json @@ -0,0 +1,2280 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HorizonStaking", + "sourceName": "contracts/staking/HorizonStaking.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "address", + "name": "stakingExtensionAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "subgraphDataServiceAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingCallerIsServiceProvider", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientIdleStake", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientShares", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientStakeForLegacyAllocations", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minRequired", + "type": "uint256" + } + ], + "name": "HorizonStakingInsufficientTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "HorizonStakingInvalidDelegationFeeCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidDelegationPoolState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxMaxVerifierCut", + "type": "uint32" + } + ], + "name": "HorizonStakingInvalidMaxVerifierCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingInvalidProvision", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "HorizonStakingInvalidThawingPeriod", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroShares", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingNotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingNothingThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingProvisionAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minShares", + "type": "uint256" + } + ], + "name": "HorizonStakingSlippageProtection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "HorizonStakingStillThawing", + "type": "error" + }, + { + "inputs": [], + "name": "HorizonStakingTooManyThawRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxTokens", + "type": "uint256" + } + ], + "name": "HorizonStakingTooManyTokens", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "HorizonStakingVerifierNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListEmptyList", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidIterations", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListInvalidZeroId", + "type": "error" + }, + { + "inputs": [], + "name": "LinkedListMaxElementsExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyController", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyGovernor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AllowedLockedVerifierSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegatedTokensWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "DelegationFeeCutSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "DelegationSlashingEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "DelegationSlashingSkipped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "MaxThawingPeriodSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "OperatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "ProvisionParametersStaged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionSlashed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ProvisionThawed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "until", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "ThawRequestCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + } + ], + "name": "ThawRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawRequestsFulfilled", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "ThawRequestsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ThawingPeriodCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensDeprovisioned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensToDelegationPoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "TokensUndelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "VerifierTokensSent", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "acceptProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToDelegationPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "addToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSharesOut", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "deprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegatedTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.Delegation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + } + ], + "name": "getDelegationFeeCut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegationPool", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.DelegationPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getIdleStake", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProviderTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProvision", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "createdAt", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxVerifierCutPending", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriodPending", + "type": "uint64" + } + ], + "internalType": "struct IHorizonStakingTypes.Provision", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getServiceProvider", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokensStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensProvisioned", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.ServiceProvider", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "getThawRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "next", + "type": "bytes32" + } + ], + "internalType": "struct IHorizonStakingTypes.ThawRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawRequestList", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "head", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tail", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "internalType": "struct LinkedList.List", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delegationRatio", + "type": "uint32" + } + ], + "name": "getTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAllowedLockedVerifier", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAuthorized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDelegationSlashingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "provisionLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "oldVerifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newVerifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "reprovision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAllowedLockedVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "feeCut", + "type": "uint256" + } + ], + "name": "setDelegationFeeCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setDelegationSlashingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "maxThawingPeriod", + "type": "uint64" + } + ], + "name": "setMaxThawingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setOperatorLocked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + } + ], + "name": "setProvisionParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensVerifier", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifierDestination", + "type": "address" + } + ], + "name": "slash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "stakeToProvision", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "newServiceProvider", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minSharesForNewProvider", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nThawRequests", + "type": "uint256" + } + ], + "name": "withdrawDelegated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b50604051615b2c380380615b2c8339810160408190526100309161041b565b828181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610351565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610351565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610351565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610351565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610351565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610351565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610351565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610351565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610351565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b039081166101c052929092166101e052506104ce915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038c91815260200190565b602060405180830381865afa1580156103a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cd919061045e565b9050826001600160a01b0382166103f85760405163218f5add60e11b81526004016100749190610480565b5092915050565b80516001600160a01b038116811461041657600080fd5b919050565b60008060006060848603121561043057600080fd5b610439846103ff565b9250610447602085016103ff565b9150610455604085016103ff565b90509250925092565b60006020828403121561047057600080fd5b610479826103ff565b9392505050565b602081526000825180602084015260005b818110156104ae5760208186018101516040868401015201610491565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516155836105a960003960006102fb015260008181610dbf015281816115b60152818161166801528181612f5401528181613e120152614172015260005050600050506000505060005050600050506000612f0d015260005050600050506000505060008181610d89015281816117cd015281816125b2015281816128c80152818161295f01528181612ac00152818161380b015281816139cb01528181613d88015261401e01526155836000f3fe6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#ExponentialRebates.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#ExponentialRebates.json new file mode 100644 index 000000000..fc0c0c29f --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#ExponentialRebates.json @@ -0,0 +1,55 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ExponentialRebates", + "sourceName": "contracts/staking/libraries/ExponentialRebates.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "fees", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "alphaNumerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "alphaDenominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lambdaNumerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lambdaDenominator", + "type": "uint32" + } + ], + "name": "exponentialRebates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x610c2d610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c806349484d811461003a575b600080fd5b61004d610048366004610a66565b61005f565b60405190815260200160405180910390f35b6000806100728660030b8660030b61011c565b9050806000036100855787915050610112565b87600003610097576000915050610112565b60006100a98560030b8560030b61011c565b905060006100b8828a8c61013c565b9050600f6100c582610153565b13156100d657899350505050610112565b60006100ff6001607f1b6100fa866100f56100f087610ae2565b610169565b610882565b61089d565b905061010b818c6108d4565b9450505050505b9695505050505050565b600061013561012f846001607f1b610920565b83610988565b9392505050565b600061014b61012f8585610920565b949350505050565b60006101636001607f1b83610b14565b92915050565b60006101796101ff607c1b610ae2565b82121561018857506000919050565b8160000361019b57506001607f1b919050565b60008213156101c55760405162461bcd60e51b81526004016101bc90610b42565b60405180910390fd5b6000806101d66001607c1b85610b69565b91508190506001607f1b6101ea8280610b7d565b6101f49190610b14565b9050610208816710e1b3be415a0000610b7d565b6102129084610bad565b92506001607f1b6102238383610b7d565b61022d9190610b14565b9050610241816705a0913f6b1e0000610b7d565b61024b9084610bad565b92506001607f1b61025c8383610b7d565b6102669190610b14565b905061027a81670168244fdac78000610b7d565b6102849084610bad565b92506001607f1b6102958383610b7d565b61029f9190610b14565b90506102b281664807432bc18000610b7d565b6102bc9084610bad565b92506001607f1b6102cd8383610b7d565b6102d79190610b14565b90506102ea81660c0135dca04000610b7d565b6102f49084610bad565b92506001607f1b6103058383610b7d565b61030f9190610b14565b9050610322816601b707b1cdc000610b7d565b61032c9084610bad565b92506001607f1b61033d8383610b7d565b6103479190610b14565b9050610359816536e0f639b800610b7d565b6103639084610bad565b92506001607f1b6103748383610b7d565b61037e9190610b14565b905061039081650618fee9f800610b7d565b61039a9084610bad565b92506001607f1b6103ab8383610b7d565b6103b59190610b14565b90506103c681649c197dcc00610b7d565b6103d09084610bad565b92506001607f1b6103e18383610b7d565b6103eb9190610b14565b90506103fc81640e30dce400610b7d565b6104069084610bad565b92506001607f1b6104178383610b7d565b6104219190610b14565b90506104328164012ebd1300610b7d565b61043c9084610bad565b92506001607f1b61044d8383610b7d565b6104579190610b14565b9050610467816317499f00610b7d565b6104719084610bad565b92506001607f1b6104828383610b7d565b61048c9190610b14565b905061049c816301a9d480610b7d565b6104a69084610bad565b92506001607f1b6104b78383610b7d565b6104c19190610b14565b90506104d081621c6380610b7d565b6104da9084610bad565b92506001607f1b6104eb8383610b7d565b6104f59190610b14565b9050610504816201c638610b7d565b61050e9084610bad565b92506001607f1b61051f8383610b7d565b6105299190610b14565b905061053781611ab8610b7d565b6105419084610bad565b92506001607f1b6105528383610b7d565b61055c9190610b14565b905061056a8161017c610b7d565b6105749084610bad565b92506001607f1b6105858383610b7d565b61058f9190610b14565b905061059c816014610b7d565b6105a69084610bad565b92506001607f1b6105b78383610b7d565b6105c19190610b14565b90506105ce816001610b7d565b6105d89084610bad565b92506001607f1b826105f26721c3677c82b4000086610b14565b6105fc9190610bad565b6106069190610bad565b925061061184610ae2565b9350600160841b841615610657577243cbaf42a000812488fc5c220ad7b97bf6e99e61064a6cf1aaddd7742e56d32fb9f9974485610b7d565b6106549190610b14565b92505b600160831b84161561069c577105d27a9f51c31b7c2f8038212a057477999161068f6e0afe10820813d65dfe6a33c07f738f85610b7d565b6106999190610b14565b92505b600160821b8416156106e157701b4c902e273a58678d6d3bfdb93db96d026106d46f02582ab704279e8efd15e0265855c47a85610b7d565b6106de9190610b14565b92505b600160811b841615610726577003b1cc971a9bb5b9867477440d6d1577506107196f1152aaa3bf81cb9fdb76eae12d02957185610b7d565b6107239190610b14565b92505b600160801b84161561076b5770015bf0a8b1457695355fb8ac404e7a79e361075e6f2f16ac6c59de6f8d5d6f63c1482a7c8685610b7d565b6107689190610b14565b92505b6001607f1b8416156107af576fd3094c70f034de4b96ff7d5b6f99fcd86107a26f4da2cbf1be5827f9eb3ad1aa9866ebb385610b7d565b6107ac9190610b14565b92505b6001607e1b8416156107f3576fa45af1e1f40c333b3de1db4dd55f29a76107e66f63afbe7ab2082ba1a0ae5e4eb1b479dc85610b7d565b6107f09190610b14565b92505b6001607d1b841615610837576f910b022db7ae67ce76b441c27035c6a161082a6f70f5a893b608861e1f58934f97aea57d85610b7d565b6108349190610b14565b92505b6001607c1b84161561087b576f88415abbe9a76bead8d00cf112e4d4a861086e6f783eafef1c0a8f3978c7f81824d62ebf85610b7d565b6108789190610b14565b92505b5050919050565b60006001607f1b6108938484610920565b6101359190610b14565b6000600160ff1b82036108c25760405162461bcd60e51b81526004016101bc90610b42565b610135836108cf84610ae2565b6109f2565b6000808212156108f65760405162461bcd60e51b81526004016101bc90610b42565b60006109028484610920565b905060008113610916576000915050610163565b607f1c9392505050565b600082158061092d575081155b1561093a57506000610163565b508181028183828161094e5761094e610afe565b0514158061096b57508282828161096757610967610afe565b0514155b156101635760405162461bcd60e51b81526004016101bc90610bd5565b6000816000036109aa5760405162461bcd60e51b81526004016101bc90610bd5565b600160ff1b831480156109be575081600019145b156109db5760405162461bcd60e51b81526004016101bc90610bd5565b8183816109ea576109ea610afe565b059392505050565b818101600083128015610a055750600082125b8015610a1057508281135b8061096b5750600083138015610a265750600082135b801561096b5750828112156101635760405162461bcd60e51b81526004016101bc90610bd5565b803563ffffffff81168114610a6157600080fd5b919050565b60008060008060008060c08789031215610a7f57600080fd5b8635955060208701359450610a9660408801610a4d565b9350610aa460608801610a4d565b9250610ab260808801610a4d565b9150610ac060a08801610a4d565b90509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201610af757610af7610acc565b5060000390565b634e487b7160e01b600052601260045260246000fd5b600082610b2357610b23610afe565b600160ff1b821460001984141615610b3d57610b3d610acc565b500590565b6020808252600d908201526c6f75742d6f662d626f756e647360981b604082015260600190565b600082610b7857610b78610afe565b500790565b80820260008212600160ff1b84141615610b9957610b99610acc565b818105831482151761016357610163610acc565b8082018281126000831280158216821582161715610bcd57610bcd610acc565b505092915050565b6020808252600890820152676f766572666c6f7760c01b60408201526060019056fea26469706673582212201cac81319f1bc19d15bc3a02519b03e3559a9cf147525a96caa8cb800f74da2864736f6c634300081b0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c806349484d811461003a575b600080fd5b61004d610048366004610a66565b61005f565b60405190815260200160405180910390f35b6000806100728660030b8660030b61011c565b9050806000036100855787915050610112565b87600003610097576000915050610112565b60006100a98560030b8560030b61011c565b905060006100b8828a8c61013c565b9050600f6100c582610153565b13156100d657899350505050610112565b60006100ff6001607f1b6100fa866100f56100f087610ae2565b610169565b610882565b61089d565b905061010b818c6108d4565b9450505050505b9695505050505050565b600061013561012f846001607f1b610920565b83610988565b9392505050565b600061014b61012f8585610920565b949350505050565b60006101636001607f1b83610b14565b92915050565b60006101796101ff607c1b610ae2565b82121561018857506000919050565b8160000361019b57506001607f1b919050565b60008213156101c55760405162461bcd60e51b81526004016101bc90610b42565b60405180910390fd5b6000806101d66001607c1b85610b69565b91508190506001607f1b6101ea8280610b7d565b6101f49190610b14565b9050610208816710e1b3be415a0000610b7d565b6102129084610bad565b92506001607f1b6102238383610b7d565b61022d9190610b14565b9050610241816705a0913f6b1e0000610b7d565b61024b9084610bad565b92506001607f1b61025c8383610b7d565b6102669190610b14565b905061027a81670168244fdac78000610b7d565b6102849084610bad565b92506001607f1b6102958383610b7d565b61029f9190610b14565b90506102b281664807432bc18000610b7d565b6102bc9084610bad565b92506001607f1b6102cd8383610b7d565b6102d79190610b14565b90506102ea81660c0135dca04000610b7d565b6102f49084610bad565b92506001607f1b6103058383610b7d565b61030f9190610b14565b9050610322816601b707b1cdc000610b7d565b61032c9084610bad565b92506001607f1b61033d8383610b7d565b6103479190610b14565b9050610359816536e0f639b800610b7d565b6103639084610bad565b92506001607f1b6103748383610b7d565b61037e9190610b14565b905061039081650618fee9f800610b7d565b61039a9084610bad565b92506001607f1b6103ab8383610b7d565b6103b59190610b14565b90506103c681649c197dcc00610b7d565b6103d09084610bad565b92506001607f1b6103e18383610b7d565b6103eb9190610b14565b90506103fc81640e30dce400610b7d565b6104069084610bad565b92506001607f1b6104178383610b7d565b6104219190610b14565b90506104328164012ebd1300610b7d565b61043c9084610bad565b92506001607f1b61044d8383610b7d565b6104579190610b14565b9050610467816317499f00610b7d565b6104719084610bad565b92506001607f1b6104828383610b7d565b61048c9190610b14565b905061049c816301a9d480610b7d565b6104a69084610bad565b92506001607f1b6104b78383610b7d565b6104c19190610b14565b90506104d081621c6380610b7d565b6104da9084610bad565b92506001607f1b6104eb8383610b7d565b6104f59190610b14565b9050610504816201c638610b7d565b61050e9084610bad565b92506001607f1b61051f8383610b7d565b6105299190610b14565b905061053781611ab8610b7d565b6105419084610bad565b92506001607f1b6105528383610b7d565b61055c9190610b14565b905061056a8161017c610b7d565b6105749084610bad565b92506001607f1b6105858383610b7d565b61058f9190610b14565b905061059c816014610b7d565b6105a69084610bad565b92506001607f1b6105b78383610b7d565b6105c19190610b14565b90506105ce816001610b7d565b6105d89084610bad565b92506001607f1b826105f26721c3677c82b4000086610b14565b6105fc9190610bad565b6106069190610bad565b925061061184610ae2565b9350600160841b841615610657577243cbaf42a000812488fc5c220ad7b97bf6e99e61064a6cf1aaddd7742e56d32fb9f9974485610b7d565b6106549190610b14565b92505b600160831b84161561069c577105d27a9f51c31b7c2f8038212a057477999161068f6e0afe10820813d65dfe6a33c07f738f85610b7d565b6106999190610b14565b92505b600160821b8416156106e157701b4c902e273a58678d6d3bfdb93db96d026106d46f02582ab704279e8efd15e0265855c47a85610b7d565b6106de9190610b14565b92505b600160811b841615610726577003b1cc971a9bb5b9867477440d6d1577506107196f1152aaa3bf81cb9fdb76eae12d02957185610b7d565b6107239190610b14565b92505b600160801b84161561076b5770015bf0a8b1457695355fb8ac404e7a79e361075e6f2f16ac6c59de6f8d5d6f63c1482a7c8685610b7d565b6107689190610b14565b92505b6001607f1b8416156107af576fd3094c70f034de4b96ff7d5b6f99fcd86107a26f4da2cbf1be5827f9eb3ad1aa9866ebb385610b7d565b6107ac9190610b14565b92505b6001607e1b8416156107f3576fa45af1e1f40c333b3de1db4dd55f29a76107e66f63afbe7ab2082ba1a0ae5e4eb1b479dc85610b7d565b6107f09190610b14565b92505b6001607d1b841615610837576f910b022db7ae67ce76b441c27035c6a161082a6f70f5a893b608861e1f58934f97aea57d85610b7d565b6108349190610b14565b92505b6001607c1b84161561087b576f88415abbe9a76bead8d00cf112e4d4a861086e6f783eafef1c0a8f3978c7f81824d62ebf85610b7d565b6108789190610b14565b92505b5050919050565b60006001607f1b6108938484610920565b6101359190610b14565b6000600160ff1b82036108c25760405162461bcd60e51b81526004016101bc90610b42565b610135836108cf84610ae2565b6109f2565b6000808212156108f65760405162461bcd60e51b81526004016101bc90610b42565b60006109028484610920565b905060008113610916576000915050610163565b607f1c9392505050565b600082158061092d575081155b1561093a57506000610163565b508181028183828161094e5761094e610afe565b0514158061096b57508282828161096757610967610afe565b0514155b156101635760405162461bcd60e51b81526004016101bc90610bd5565b6000816000036109aa5760405162461bcd60e51b81526004016101bc90610bd5565b600160ff1b831480156109be575081600019145b156109db5760405162461bcd60e51b81526004016101bc90610bd5565b8183816109ea576109ea610afe565b059392505050565b818101600083128015610a055750600082125b8015610a1057508281135b8061096b5750600083138015610a265750600082135b801561096b5750828112156101635760405162461bcd60e51b81526004016101bc90610bd5565b803563ffffffff81168114610a6157600080fd5b919050565b60008060008060008060c08789031215610a7f57600080fd5b8635955060208701359450610a9660408801610a4d565b9350610aa460608801610a4d565b9250610ab260808801610a4d565b9150610ac060a08801610a4d565b90509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201610af757610af7610acc565b5060000390565b634e487b7160e01b600052601260045260246000fd5b600082610b2357610b23610afe565b600160ff1b821460001984141615610b3d57610b3d610acc565b500590565b6020808252600d908201526c6f75742d6f662d626f756e647360981b604082015260600190565b600082610b7857610b78610afe565b500790565b80820260008212600160ff1b84141615610b9957610b99610acc565b818105831482151761016357610163610acc565b8082018281126000831280158216821582161715610bcd57610bcd610acc565b505092915050565b6020808252600890820152676f766572666c6f7760c01b60408201526060019056fea26469706673582212201cac81319f1bc19d15bc3a02519b03e3559a9cf147525a96caa8cb800f74da2864736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#HorizonStakingExtension.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#HorizonStakingExtension.json new file mode 100644 index 000000000..7cd249086 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/HorizonStakingExtension#HorizonStakingExtension.json @@ -0,0 +1,1263 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HorizonStakingExtension", + "sourceName": "contracts/staking/HorizonStakingExtension.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "address", + "name": "subgraphDataServiceAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyController", + "type": "error" + }, + { + "inputs": [], + "name": "ManagedOnlyGovernor", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "PPMMathInvalidPPM", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "poi", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isPublic", + "type": "bool" + } + ], + "name": "AllocationClosed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "counterpart", + "type": "address" + } + ], + "name": "CounterpartStakingAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "assetHolder", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "protocolTax", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curationFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "queryFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "queryRebates", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delegationRewards", + "type": "uint256" + } + ], + "name": "RebateCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "StakeDelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "StakeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredDelegationReturnedToDelegator", + "type": "event" + }, + { + "inputs": [], + "name": "__DEPRECATED_getThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "poi", + "type": "bytes32" + } + ], + "name": "closeAllocation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "getAllocation", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "createdAtEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "closedAtEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collectedFees", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "__DEPRECATED_effectiveAllocation", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerAllocatedToken", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "distributedRebates", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingExtension.Allocation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "getAllocationData", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "getAllocationState", + "outputs": [ + { + "internalType": "enum IHorizonStakingExtension.AllocationState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegatedTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegation", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.Delegation", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + } + ], + "name": "getDelegationFeeCut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getDelegationPool", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.DelegationPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getIdleStake", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "indexer", + "type": "address" + } + ], + "name": "getIndexerStakedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxThawingPeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProviderTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getProvision", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sharesThawing", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxVerifierCut", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "createdAt", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxVerifierCutPending", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "thawingPeriodPending", + "type": "uint64" + } + ], + "internalType": "struct IHorizonStakingTypes.Provision", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getServiceProvider", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "tokensStaked", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensProvisioned", + "type": "uint256" + } + ], + "internalType": "struct IHorizonStakingTypes.ServiceProvider", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getSubgraphAllocatedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "thawRequestId", + "type": "bytes32" + } + ], + "name": "getThawRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "thawingUntil", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "next", + "type": "bytes32" + } + ], + "internalType": "struct IHorizonStakingTypes.ThawRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawRequestList", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "head", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tail", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "internalType": "struct LinkedList.List", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "getThawedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "delegationRatio", + "type": "uint32" + } + ], + "name": "getTokensAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "indexer", + "type": "address" + } + ], + "name": "hasStake", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "isActiveAllocation", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "isAllocation", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "isAllowedLockedVerifier", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isDelegationSlashingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "counterpart", + "type": "address" + } + ], + "name": "setCounterpartStakingAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6101e060405234801561001157600080fd5b5060405161396738038061396783398101604081905261003091610411565b818181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610347565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610347565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610347565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610347565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610347565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610347565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610347565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610347565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610347565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b03166101c052506104b4915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038291815260200190565b602060405180830381865afa15801561039f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c39190610444565b9050826001600160a01b0382166103ee5760405163218f5add60e11b81526004016100749190610466565b5092915050565b80516001600160a01b038116811461040c57600080fd5b919050565b6000806040838503121561042457600080fd5b61042d836103f5565b915061043b602084016103f5565b90509250929050565b60006020828403121561045657600080fd5b61045f826103f5565b9392505050565b602081526000825180602084015260005b818110156104945760208186018101516040868401015201610477565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516133d761059060003960008181611c3601528181611e3601526123f00152600061205b015260005050600061178501526000818161213d0152818161280501526129080152600081816112c70152611b6f015260008181610bbf01528181610cbc01528181610ed601526116dc015260005050600050506000505060008181611044015281816111fa01528181612023015281816121b20152818161239a015281816124c2015261263201526133d76000f3fe6080604052600436106101f25760003560e01c806398c657dc1161010d578063b6363cf2116100a0578063e2e1e8e91161006f578063e2e1e8e914610a0b578063e73e14bf14610a38578063f1d60d6614610a70578063fb744cc014610a90578063fc54fb2714610ab057600080fd5b8063b6363cf2146108dd578063b7ca724114610927578063c0641994146109c1578063ccebcabb146109dc57600080fd5b8063a4c0ed36116100dc578063a4c0ed3614610837578063a784d49814610857578063ac9650d814610877578063ae4fe67a146108a457600080fd5b806398c657dc1461072d5780639ce7abe51461075a578063a212daf81461077a578063a2594d821461081757600080fd5b8063561285e411610185578063872d048911610154578063872d04891461064c5780638cc01c861461066c5780638d3c100a146106ed5780639054e3431461070d57600080fd5b8063561285e4146105a95780636a3ca383146105fc5780637573ef4f1461062c5780637a7664601461031157600080fd5b806325d9897e116101c157806325d9897e1461036957806339514ad21461047957806344c32a61146104ab57806355c85269146104cb57600080fd5b806308ce5f68146102495780630e0229231461027c5780631787e69f146103115780631ae720451461034757600080fd5b366102445760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b600080fd5b34801561025557600080fd5b50610269610264366004612bec565b610ac8565b6040519081526020015b60405180910390f35b34801561028857600080fd5b5061029c610297366004612c25565b610add565b604051610273919060006101208201905060018060a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b34801561031d57600080fd5b5061026961032c366004612c25565b6001600160a01b03166000908152600e602052604090205490565b34801561035357600080fd5b50610367610362366004612c25565b610bbd565b005b34801561037557600080fd5b5061046c610384366004612bec565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516102739190612c42565b34801561048557600080fd5b50601a546001600160401b03165b6040516001600160401b039091168152602001610273565b3480156104b757600080fd5b506103676104c6366004612cd2565b610cba565b3480156104d757600080fd5b506105776104e6366004612c25565b6001600160a01b039081166000908152600f602090815260408083208151610120810183528154909516808652600182015493860184905260028201549286018390526003820154606087015260048201546080870152600582015460a0870152600682015460c0870152600782015460e08701819052600890920154610100909601959095529394919390929091565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610273565b3480156105b557600080fd5b506105c96105c4366004612bec565b610d68565b60405161027391908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561060857600080fd5b5061061c610617366004612c25565b610df6565b6040519015158152602001610273565b34801561063857600080fd5b50610269610647366004612cfe565b610e1b565b34801561065857600080fd5b50610269610667366004612d4d565b610e7f565b34801561067857600080fd5b506106d2610687366004612c25565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b60408051825181526020928301519281019290925201610273565b3480156106f957600080fd5b50610367610708366004612d96565b610ed4565b34801561071957600080fd5b50610269610728366004612dbb565b6113a0565b34801561073957600080fd5b5061074d610748366004612c25565b611488565b6040516102739190612e11565b34801561076657600080fd5b50610367610775366004612e81565b611493565b34801561078657600080fd5b506105c9610795366004612dbb565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561082357600080fd5b50610367610832366004612c25565b6115be565b34801561084357600080fd5b50610367610852366004612ed5565b6116da565b34801561086357600080fd5b50610269610872366004612c25565b6118e7565b34801561088357600080fd5b50610897610892366004612f30565b6118f2565b6040516102739190612fc9565b3480156108b057600080fd5b5061061c6108bf366004612c25565b6001600160a01b031660009081526022602052604090205460ff1690565b3480156108e957600080fd5b5061061c6108f8366004612bec565b6001600160a01b0380821660009081526015602090815260408083209386168352929052205460ff1692915050565b34801561093357600080fd5b50610996610942366004613049565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b0316908201529181015190820152606001610273565b3480156109cd57600080fd5b50600d5463ffffffff16610493565b3480156109e857600080fd5b506109fc6109f7366004612dbb565b6119d9565b60405190518152602001610273565b348015610a1757600080fd5b50610269610a26366004613049565b60009081526010602052604090205490565b348015610a4457600080fd5b5061061c610a53366004612c25565b6001600160a01b03166000908152600e6020526040902054151590565b348015610a7c57600080fd5b5061061c610a8b366004612c25565b611a2b565b348015610a9c57600080fd5b50610269610aab366004612bec565b611a50565b348015610abc57600080fd5b5060205460ff1661061c565b6000610ad48383611a5c565b90505b92915050565b610b3860405180610120016040528060006001600160a01b0316815260200160008019168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b039081166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e08301526008015461010082015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190613062565b6001600160a01b0316336001600160a01b031614610c7057604051635d9044cd60e01b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0383169081179091556040517f690e9b982dc9aefaa1cfed186a2d2045a638013d658104102c9437235bee4b6090600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c919061307f565b15610d5a57604051632b37d9d160e21b815260040160405180910390fd5b610d648282611a94565b5050565b610d936040518060800160405280600081526020016000815260200160008152602001600081525090565b610dbe6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000610dca8585611e32565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b60006001610e0383611eb6565b6002811115610e1457610e14612dfb565b1492915050565b6001600160a01b038084166000908152601c60209081526040808320938616835292905290812081836002811115610e5557610e55612dfb565b6002811115610e6657610e66612dfb565b81526020019081526020016000205490505b9392505050565b600080610e8c8585611a5c565b90506000610e9a8686611f0f565b90506000610eae63ffffffff8616846130b7565b90506000610ebc8383611f3a565b9050610ec881856130ce565b98975050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061307f565b15610f7457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038116610fb35760405162461bcd60e51b815260206004820152600660248201526521616c6c6f6360d01b604482015260640161023b565b6000610fbe82611eb6565b90506000816002811115610fd457610fd4612dfb565b0361100c5760405162461bcd60e51b81526020600482015260086024820152670858dbdb1b1958dd60c21b604482015260640161023b565b8260000361101957505050565b6001600160a01b0382166000908152600f6020526040812060018101549091859080808061107333867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190611f51565b600d5461108e908690600160401b900463ffffffff1661200e565b935061109a84866130e1565b600d549095506110bb9087908790640100000000900463ffffffff16612047565b92506110c783866130e1565b94508487600501546110d991906130ce565b6005880155600287015460009015806110ff5750601954600160a01b900463ffffffff16155b6111ca5760058801546002890154600d546019546040516349484d8160e01b81526004810194909452602484019290925263ffffffff600160a01b80830482166044860152600160c01b928390048216606486015283048116608485015291041660a482015273__$8eb3cac1482a31d7a7f2cbe7dc8bdcd821$__906349484d819060c401602060405180830381865af41580156111a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c591906130f4565b6111cd565b60005b90506111dd81896008015461225a565b92506111e98387611f3a565b92506112296111f884886130e1565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690612274565b82156112915782886008015461123f91906130ce565b60088901558754611259906001600160a01b0316846122bc565b915061126582846130e1565b88546001600160a01b03908116600081815260176020526040902054929550611291928692161561234e565b5086546001600160a01b038a8116918891167ff5ded07502b6feba4c13b19a0c6646efd4b4119f439bcbd49076e4f0ed1eec4b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611323573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134791906130f4565b604080516001600160a01b039093168352602083019190915281018f9052606081018990526080810188905260a081018a905260c0810187905260e081018690526101000160405180910390a450505050505050505050565b6001600160a01b038084166000908152601e60209081526040808320868516845282528083209385168352929052908120600381015482036113e6576000915050610e78565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b801561147c576000818152601d602052604090206001810154426001600160401b039091161161146b5760028301546001840154825461145091906130b7565b61145a919061310d565b61146490856130ce565b9350611471565b5061147c565b600201549050611410565b50909695505050505050565b6000610ad782611eb6565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f89190613062565b6001600160a01b0316336001600160a01b0316146115585760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611586908690869060040161312f565b600060405180830381600087803b1580156115a057600080fd5b505af11580156115b4573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116239190613062565b6001600160a01b0316336001600160a01b0316146116835760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156116be57600080fd5b505af11580156116d2573d6000803e3d6000fd5b505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c919061307f565b1561177a57604051632b37d9d160e21b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117e15760405162461bcd60e51b815260206004820152600c60248201526b4f4e4c595f4741544557415960a01b604482015260640161023b565b6018546001600160a01b0385811691161461183e5760405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c315f5354414b494e475f5448524f5547485f4252494447450000604482015260640161023b565b60008061184d838501856131a4565b909250905060ff8216611882576000818060200190518101906118709190613255565b905061187c86826123c4565b506116d2565b60001960ff8316016118b0576000818060200190518101906118a491906132a2565b905061187c86826123d0565b60405162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f434f444560a01b604482015260640161023b565b6000610ad782612740565b604080516000815260208101909152606090826001600160401b0381111561191c5761191c61315e565b60405190808252806020026020018201604052801561194f57816020015b606081526020019060019003908161193a5790505b50915060005b838110156119d1576119ac3086868481811061197357611973613302565b90506020028101906119859190613318565b856040516020016119989392919061335e565b60405160208183030381529060405261278b565b8382815181106119be576119be613302565b6020908102919091010152600101611955565b505092915050565b6040805160208101909152600081526040805160208101909152600081526000611a038686611e32565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b600080611a3783611eb6565b6002811115611a4857611a48612dfb565b141592915050565b6000610ad48383611f0f565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610ad491906130e1565b6000611a9f83611eb6565b90506001816002811115611ab557611ab5612dfb565b14611aec5760405162461bcd60e51b81526020600482015260076024820152662161637469766560c81b604482015260640161023b565b6001600160a01b038381166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600801546101008201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef91906130f4565b608082018190526060820151600091611c079161225a565b9050600082600001516001600160a01b0316336001600160a01b03161480611c78575082516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600090815260156020908152604080832093909416825291909152205460ff165b600d54909150600160801b900463ffffffff1682111580611c9b57506040830151155b15611cd55780611cd55760405162461bcd60e51b8152602060048201526005602482015264042c2eae8d60db1b604482015260640161023b565b60808301516001600160a01b0387166000908152600f6020526040908190206004019190915583015115611db957808015611d0f57508415155b15611d2757611d22868460000151612801565b611d36565b611d3483602001516128e7565b505b60408084015184516001600160a01b03166000908152600e6020529190912060010154611d6391906130e1565b83516001600160a01b03166000908152600e602090815260408083206001019390935582860151818701518352601090915291902054611da391906130e1565b6020808501516000908152601090915260409020555b60208084015184516080808701516040808901518151928352958201959095523394810194909452606084018990528415908401526001600160a01b03808a16939116907ff6725dd105a6fc88bb79a6e4627f128577186c567a17c94818d201c2a4ce14039060a00160405180910390a4505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603611e8b57506001600160a01b0382166000908152601460205260409020610ad7565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610ad7565b6001600160a01b038082166000908152600f6020526040812080549192909116611ee35750600092915050565b600381015415801590611ef857506004810154155b15611f065750600192915050565b50600292915050565b600080611f1c8484611e32565b905080600501548160020154611f3291906130e1565b949350505050565b600081831115611f4a5781610ad4565b5090919050565b8015612009576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061307f565b6120095760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161023b565b505050565b60008061201b8484612975565b9050610ad4817f000000000000000000000000000000000000000000000000000000000000000061121a565b60008260000361205957506000610e78565b7f00000000000000000000000000000000000000000000000000000000000000006000831580159061209357506001600160a01b03821615155b90508080156121065750604051634c4ea0ed60e01b8152600481018790526001600160a01b03831690634c4ea0ed90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612106919061307f565b1561224e5760006121178686612975565b90508015612244576040516307470bfb60e21b8152600481018890526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631d1c2fec906024016020604051808303816000875af1158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa91906130f4565b506121e283827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906129c7565b60405163102ae65160e31b815260048101889052602481018290526001600160a01b03841690638157328890604401600060405180830381600087803b15801561222b57600080fd5b505af115801561223f573d6000803e3d6000fd5b505050505b9250610e78915050565b50600095945050505050565b600081831161226a576000610ad4565b610ad482846130e1565b8015610d6457604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156116be57600080fd5b6001600160a01b03821660009081526014602052604081206002810154829190158015906122fb57508054600160401b900463ffffffff16620f424010155b156123465780546000906123219063ffffffff600160401b9091048116908790612a0216565b905061232d81866130e1565b925082826002015461233f91906130ce565b6002830155505b509392505050565b8260000361235b57505050565b801561236b576120098284612a69565b6001600160a01b03808316600090815260176020526040902054166123be81156123955781612397565b835b857f00000000000000000000000000000000000000000000000000000000000000006121d2565b50505050565b80516120098184612a69565b80516001600160a01b039081166000908152601b602090815260408083207f0000000000000000000000000000000000000000000000000000000000000000909416835292905290812060030154600160601b90046001600160401b031690036124695760405162461bcd60e51b815260206004820152600a60248201526910b83937bb34b9b4b7b760b11b604482015260640161023b565b80516001600160a01b03908116600090815260146020908152604080832082860151909416835260048401909152902060028201541580156124bb575060038201541515806124bb5750600682015415155b156125b5577f0000000000000000000000000000000000000000000000000000000000000000602084015160405163a9059cbb60e01b81526001600160a01b0391821660048201526024810187905291169063a9059cbb906044016020604051808303816000875af1158015612535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612559919061307f565b5082602001516001600160a01b031683600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de866040516125a791815260200190565b60405180910390a350505050565b60008260020154600014806125d1575082600501548360020154145b61260757826005015483600201546125e991906130e1565b60038401546125f890876130b7565b612602919061310d565b612609565b845b905080158061261f5750670de0b6b3a764000085105b156126ae576126548460200151866121d27f000000000000000000000000000000000000000000000000000000000000000090565b83602001516001600160a01b031684600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de876040516126a191815260200190565b60405180910390a3612739565b8483600201546126be91906130ce565b600284015560038301546126d39082906130ce565b600384015581546126e59082906130ce565b82556020808501518551604080518981529384018590526001600160a01b039283169391909216917fcd0366dce5247d874ffc60a762aa7abbb82c1695bbb171609c1b8861e279eb73910160405180910390a35b5050505050565b6001600160a01b0381166000908152600e6020526040812060028101546001820154600483015492549192909161277791906130e1565b61278191906130e1565b610ad791906130e1565b6060600080846001600160a01b0316846040516127a89190613385565b600060405180830381855af49150503d80600081146127e3576040519150601f19603f3d011682016040523d82523d6000602084013e6127e8565b606091505b50915091506127f8858383612ae8565b95945050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000604051636dba849360e11b81526001600160a01b038581166004830152919091169063db750926906024016020604051808303816000875af115801561286e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289291906130f4565b9050806000036128a157505050565b60006128ad8383612b44565b905060006128bb82846130e1565b6001600160a01b038086166000908152601760205260409020549192506127399183918791161561234e565b6040516377561f0760e11b8152600481018290526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063eeac3e0e906024016020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad791906130f4565b600061298482620f4240101590565b82906129a657604051633dc311df60e01b815260040161023b91815260200190565b506129bd6129b783620f42406130e1565b84612a02565b610ad490846130e1565b80156120095760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401611f8e565b6000612a1183620f4240101590565b80612a245750612a2482620f4240101590565b83839091612a4e5760405163768bf0eb60e11b81526004810192909252602482015260440161023b565b50620f42409050612a5f83856130b7565b610ad4919061310d565b6001600160a01b0382166000908152600e6020526040902054612a8d9082906130ce565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290612adc9084815260200190565b60405180910390a25050565b606082612afd57612af882612bab565b610e78565b8151158015612b1457506001600160a01b0384163b155b15612b3d57604051639996b31560e01b81526001600160a01b038516600482015260240161023b565b5080610e78565b6001600160a01b0382166000908152601460205260408120600281015482919015801590612b8457508054640100000000900463ffffffff16620f424010155b156123465780546000906123219063ffffffff6401000000009091048116908790612a0216565b805115612bbb5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114612bd457600080fd5b60008060408385031215612bff57600080fd5b8235612c0a81612bd7565b91506020830135612c1a81612bd7565b809150509250929050565b600060208284031215612c3757600080fd5b8135610ad481612bd7565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151612cb060c084018263ffffffff169052565b5060e0830151612ccb60e08401826001600160401b03169052565b5092915050565b60008060408385031215612ce557600080fd5b8235612cf081612bd7565b946020939093013593505050565b600080600060608486031215612d1357600080fd5b8335612d1e81612bd7565b92506020840135612d2e81612bd7565b9150604084013560038110612d4257600080fd5b809150509250925092565b600080600060608486031215612d6257600080fd5b8335612d6d81612bd7565b92506020840135612d7d81612bd7565b9150604084013563ffffffff81168114612d4257600080fd5b60008060408385031215612da957600080fd5b823591506020830135612c1a81612bd7565b600080600060608486031215612dd057600080fd5b8335612ddb81612bd7565b92506020840135612deb81612bd7565b91506040840135612d4281612bd7565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612e3357634e487b7160e01b600052602160045260246000fd5b91905290565b60008083601f840112612e4b57600080fd5b5081356001600160401b03811115612e6257600080fd5b602083019150836020828501011115612e7a57600080fd5b9250929050565b600080600060408486031215612e9657600080fd5b8335612ea181612bd7565b925060208401356001600160401b03811115612ebc57600080fd5b612ec886828701612e39565b9497909650939450505050565b60008060008060608587031215612eeb57600080fd5b8435612ef681612bd7565b93506020850135925060408501356001600160401b03811115612f1857600080fd5b612f2487828801612e39565b95989497509550505050565b60008060208385031215612f4357600080fd5b82356001600160401b03811115612f5957600080fd5b8301601f81018513612f6a57600080fd5b80356001600160401b03811115612f8057600080fd5b8560208260051b8401011115612f9557600080fd5b6020919091019590945092505050565b60005b83811015612fc0578181015183820152602001612fa8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561303d57603f198786030184528151805180875261301a816020890160208501612fa5565b601f01601f19169590950160209081019550938401939190910190600101612ff1565b50929695505050505050565b60006020828403121561305b57600080fd5b5035919050565b60006020828403121561307457600080fd5b8151610ad481612bd7565b60006020828403121561309157600080fd5b81518015158114610ad457600080fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610ad757610ad76130a1565b80820180821115610ad757610ad76130a1565b81810381811115610ad757610ad76130a1565b60006020828403121561310657600080fd5b5051919050565b60008261312a57634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561319c5761319c61315e565b604052919050565b600080604083850312156131b757600080fd5b823560ff811681146131c857600080fd5b915060208301356001600160401b038111156131e357600080fd5b8301601f810185136131f457600080fd5b80356001600160401b0381111561320d5761320d61315e565b613220601f8201601f1916602001613174565b81815286602083850101111561323557600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000602082840312801561326857600080fd5b50604051602081016001600160401b038111828210171561328b5761328b61315e565b604052825161329981612bd7565b81529392505050565b600060408284031280156132b557600080fd5b50604080519081016001600160401b03811182821017156132d8576132d861315e565b60405282516132e681612bd7565b815260208301516132f681612bd7565b60208201529392505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261332f57600080fd5b8301803591506001600160401b0382111561334957600080fd5b602001915036819003821315612e7a57600080fd5b82848237600083820160008152835161337b818360208801612fa5565b0195945050505050565b60008251613397818460208701612fa5565b919091019291505056fea264697066735822122038ad83d20c219353421029f1ad8c4f7667d5f0e86af1579c64603bb56827d86064736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106101f25760003560e01c806398c657dc1161010d578063b6363cf2116100a0578063e2e1e8e91161006f578063e2e1e8e914610a0b578063e73e14bf14610a38578063f1d60d6614610a70578063fb744cc014610a90578063fc54fb2714610ab057600080fd5b8063b6363cf2146108dd578063b7ca724114610927578063c0641994146109c1578063ccebcabb146109dc57600080fd5b8063a4c0ed36116100dc578063a4c0ed3614610837578063a784d49814610857578063ac9650d814610877578063ae4fe67a146108a457600080fd5b806398c657dc1461072d5780639ce7abe51461075a578063a212daf81461077a578063a2594d821461081757600080fd5b8063561285e411610185578063872d048911610154578063872d04891461064c5780638cc01c861461066c5780638d3c100a146106ed5780639054e3431461070d57600080fd5b8063561285e4146105a95780636a3ca383146105fc5780637573ef4f1461062c5780637a7664601461031157600080fd5b806325d9897e116101c157806325d9897e1461036957806339514ad21461047957806344c32a61146104ab57806355c85269146104cb57600080fd5b806308ce5f68146102495780630e0229231461027c5780631787e69f146103115780631ae720451461034757600080fd5b366102445760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b600080fd5b34801561025557600080fd5b50610269610264366004612bec565b610ac8565b6040519081526020015b60405180910390f35b34801561028857600080fd5b5061029c610297366004612c25565b610add565b604051610273919060006101208201905060018060a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b34801561031d57600080fd5b5061026961032c366004612c25565b6001600160a01b03166000908152600e602052604090205490565b34801561035357600080fd5b50610367610362366004612c25565b610bbd565b005b34801561037557600080fd5b5061046c610384366004612bec565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516102739190612c42565b34801561048557600080fd5b50601a546001600160401b03165b6040516001600160401b039091168152602001610273565b3480156104b757600080fd5b506103676104c6366004612cd2565b610cba565b3480156104d757600080fd5b506105776104e6366004612c25565b6001600160a01b039081166000908152600f602090815260408083208151610120810183528154909516808652600182015493860184905260028201549286018390526003820154606087015260048201546080870152600582015460a0870152600682015460c0870152600782015460e08701819052600890920154610100909601959095529394919390929091565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610273565b3480156105b557600080fd5b506105c96105c4366004612bec565b610d68565b60405161027391908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561060857600080fd5b5061061c610617366004612c25565b610df6565b6040519015158152602001610273565b34801561063857600080fd5b50610269610647366004612cfe565b610e1b565b34801561065857600080fd5b50610269610667366004612d4d565b610e7f565b34801561067857600080fd5b506106d2610687366004612c25565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b60408051825181526020928301519281019290925201610273565b3480156106f957600080fd5b50610367610708366004612d96565b610ed4565b34801561071957600080fd5b50610269610728366004612dbb565b6113a0565b34801561073957600080fd5b5061074d610748366004612c25565b611488565b6040516102739190612e11565b34801561076657600080fd5b50610367610775366004612e81565b611493565b34801561078657600080fd5b506105c9610795366004612dbb565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561082357600080fd5b50610367610832366004612c25565b6115be565b34801561084357600080fd5b50610367610852366004612ed5565b6116da565b34801561086357600080fd5b50610269610872366004612c25565b6118e7565b34801561088357600080fd5b50610897610892366004612f30565b6118f2565b6040516102739190612fc9565b3480156108b057600080fd5b5061061c6108bf366004612c25565b6001600160a01b031660009081526022602052604090205460ff1690565b3480156108e957600080fd5b5061061c6108f8366004612bec565b6001600160a01b0380821660009081526015602090815260408083209386168352929052205460ff1692915050565b34801561093357600080fd5b50610996610942366004613049565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b0316908201529181015190820152606001610273565b3480156109cd57600080fd5b50600d5463ffffffff16610493565b3480156109e857600080fd5b506109fc6109f7366004612dbb565b6119d9565b60405190518152602001610273565b348015610a1757600080fd5b50610269610a26366004613049565b60009081526010602052604090205490565b348015610a4457600080fd5b5061061c610a53366004612c25565b6001600160a01b03166000908152600e6020526040902054151590565b348015610a7c57600080fd5b5061061c610a8b366004612c25565b611a2b565b348015610a9c57600080fd5b50610269610aab366004612bec565b611a50565b348015610abc57600080fd5b5060205460ff1661061c565b6000610ad48383611a5c565b90505b92915050565b610b3860405180610120016040528060006001600160a01b0316815260200160008019168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b039081166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e08301526008015461010082015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190613062565b6001600160a01b0316336001600160a01b031614610c7057604051635d9044cd60e01b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0383169081179091556040517f690e9b982dc9aefaa1cfed186a2d2045a638013d658104102c9437235bee4b6090600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c919061307f565b15610d5a57604051632b37d9d160e21b815260040160405180910390fd5b610d648282611a94565b5050565b610d936040518060800160405280600081526020016000815260200160008152602001600081525090565b610dbe6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000610dca8585611e32565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b60006001610e0383611eb6565b6002811115610e1457610e14612dfb565b1492915050565b6001600160a01b038084166000908152601c60209081526040808320938616835292905290812081836002811115610e5557610e55612dfb565b6002811115610e6657610e66612dfb565b81526020019081526020016000205490505b9392505050565b600080610e8c8585611a5c565b90506000610e9a8686611f0f565b90506000610eae63ffffffff8616846130b7565b90506000610ebc8383611f3a565b9050610ec881856130ce565b98975050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061307f565b15610f7457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038116610fb35760405162461bcd60e51b815260206004820152600660248201526521616c6c6f6360d01b604482015260640161023b565b6000610fbe82611eb6565b90506000816002811115610fd457610fd4612dfb565b0361100c5760405162461bcd60e51b81526020600482015260086024820152670858dbdb1b1958dd60c21b604482015260640161023b565b8260000361101957505050565b6001600160a01b0382166000908152600f6020526040812060018101549091859080808061107333867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190611f51565b600d5461108e908690600160401b900463ffffffff1661200e565b935061109a84866130e1565b600d549095506110bb9087908790640100000000900463ffffffff16612047565b92506110c783866130e1565b94508487600501546110d991906130ce565b6005880155600287015460009015806110ff5750601954600160a01b900463ffffffff16155b6111ca5760058801546002890154600d546019546040516349484d8160e01b81526004810194909452602484019290925263ffffffff600160a01b80830482166044860152600160c01b928390048216606486015283048116608485015291041660a482015273__$8eb3cac1482a31d7a7f2cbe7dc8bdcd821$__906349484d819060c401602060405180830381865af41580156111a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c591906130f4565b6111cd565b60005b90506111dd81896008015461225a565b92506111e98387611f3a565b92506112296111f884886130e1565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690612274565b82156112915782886008015461123f91906130ce565b60088901558754611259906001600160a01b0316846122bc565b915061126582846130e1565b88546001600160a01b03908116600081815260176020526040902054929550611291928692161561234e565b5086546001600160a01b038a8116918891167ff5ded07502b6feba4c13b19a0c6646efd4b4119f439bcbd49076e4f0ed1eec4b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611323573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134791906130f4565b604080516001600160a01b039093168352602083019190915281018f9052606081018990526080810188905260a081018a905260c0810187905260e081018690526101000160405180910390a450505050505050505050565b6001600160a01b038084166000908152601e60209081526040808320868516845282528083209385168352929052908120600381015482036113e6576000915050610e78565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b801561147c576000818152601d602052604090206001810154426001600160401b039091161161146b5760028301546001840154825461145091906130b7565b61145a919061310d565b61146490856130ce565b9350611471565b5061147c565b600201549050611410565b50909695505050505050565b6000610ad782611eb6565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f89190613062565b6001600160a01b0316336001600160a01b0316146115585760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611586908690869060040161312f565b600060405180830381600087803b1580156115a057600080fd5b505af11580156115b4573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116239190613062565b6001600160a01b0316336001600160a01b0316146116835760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156116be57600080fd5b505af11580156116d2573d6000803e3d6000fd5b505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c919061307f565b1561177a57604051632b37d9d160e21b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117e15760405162461bcd60e51b815260206004820152600c60248201526b4f4e4c595f4741544557415960a01b604482015260640161023b565b6018546001600160a01b0385811691161461183e5760405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c315f5354414b494e475f5448524f5547485f4252494447450000604482015260640161023b565b60008061184d838501856131a4565b909250905060ff8216611882576000818060200190518101906118709190613255565b905061187c86826123c4565b506116d2565b60001960ff8316016118b0576000818060200190518101906118a491906132a2565b905061187c86826123d0565b60405162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f434f444560a01b604482015260640161023b565b6000610ad782612740565b604080516000815260208101909152606090826001600160401b0381111561191c5761191c61315e565b60405190808252806020026020018201604052801561194f57816020015b606081526020019060019003908161193a5790505b50915060005b838110156119d1576119ac3086868481811061197357611973613302565b90506020028101906119859190613318565b856040516020016119989392919061335e565b60405160208183030381529060405261278b565b8382815181106119be576119be613302565b6020908102919091010152600101611955565b505092915050565b6040805160208101909152600081526040805160208101909152600081526000611a038686611e32565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b600080611a3783611eb6565b6002811115611a4857611a48612dfb565b141592915050565b6000610ad48383611f0f565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610ad491906130e1565b6000611a9f83611eb6565b90506001816002811115611ab557611ab5612dfb565b14611aec5760405162461bcd60e51b81526020600482015260076024820152662161637469766560c81b604482015260640161023b565b6001600160a01b038381166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600801546101008201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef91906130f4565b608082018190526060820151600091611c079161225a565b9050600082600001516001600160a01b0316336001600160a01b03161480611c78575082516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600090815260156020908152604080832093909416825291909152205460ff165b600d54909150600160801b900463ffffffff1682111580611c9b57506040830151155b15611cd55780611cd55760405162461bcd60e51b8152602060048201526005602482015264042c2eae8d60db1b604482015260640161023b565b60808301516001600160a01b0387166000908152600f6020526040908190206004019190915583015115611db957808015611d0f57508415155b15611d2757611d22868460000151612801565b611d36565b611d3483602001516128e7565b505b60408084015184516001600160a01b03166000908152600e6020529190912060010154611d6391906130e1565b83516001600160a01b03166000908152600e602090815260408083206001019390935582860151818701518352601090915291902054611da391906130e1565b6020808501516000908152601090915260409020555b60208084015184516080808701516040808901518151928352958201959095523394810194909452606084018990528415908401526001600160a01b03808a16939116907ff6725dd105a6fc88bb79a6e4627f128577186c567a17c94818d201c2a4ce14039060a00160405180910390a4505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603611e8b57506001600160a01b0382166000908152601460205260409020610ad7565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610ad7565b6001600160a01b038082166000908152600f6020526040812080549192909116611ee35750600092915050565b600381015415801590611ef857506004810154155b15611f065750600192915050565b50600292915050565b600080611f1c8484611e32565b905080600501548160020154611f3291906130e1565b949350505050565b600081831115611f4a5781610ad4565b5090919050565b8015612009576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061307f565b6120095760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161023b565b505050565b60008061201b8484612975565b9050610ad4817f000000000000000000000000000000000000000000000000000000000000000061121a565b60008260000361205957506000610e78565b7f00000000000000000000000000000000000000000000000000000000000000006000831580159061209357506001600160a01b03821615155b90508080156121065750604051634c4ea0ed60e01b8152600481018790526001600160a01b03831690634c4ea0ed90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612106919061307f565b1561224e5760006121178686612975565b90508015612244576040516307470bfb60e21b8152600481018890526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631d1c2fec906024016020604051808303816000875af1158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa91906130f4565b506121e283827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906129c7565b60405163102ae65160e31b815260048101889052602481018290526001600160a01b03841690638157328890604401600060405180830381600087803b15801561222b57600080fd5b505af115801561223f573d6000803e3d6000fd5b505050505b9250610e78915050565b50600095945050505050565b600081831161226a576000610ad4565b610ad482846130e1565b8015610d6457604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156116be57600080fd5b6001600160a01b03821660009081526014602052604081206002810154829190158015906122fb57508054600160401b900463ffffffff16620f424010155b156123465780546000906123219063ffffffff600160401b9091048116908790612a0216565b905061232d81866130e1565b925082826002015461233f91906130ce565b6002830155505b509392505050565b8260000361235b57505050565b801561236b576120098284612a69565b6001600160a01b03808316600090815260176020526040902054166123be81156123955781612397565b835b857f00000000000000000000000000000000000000000000000000000000000000006121d2565b50505050565b80516120098184612a69565b80516001600160a01b039081166000908152601b602090815260408083207f0000000000000000000000000000000000000000000000000000000000000000909416835292905290812060030154600160601b90046001600160401b031690036124695760405162461bcd60e51b815260206004820152600a60248201526910b83937bb34b9b4b7b760b11b604482015260640161023b565b80516001600160a01b03908116600090815260146020908152604080832082860151909416835260048401909152902060028201541580156124bb575060038201541515806124bb5750600682015415155b156125b5577f0000000000000000000000000000000000000000000000000000000000000000602084015160405163a9059cbb60e01b81526001600160a01b0391821660048201526024810187905291169063a9059cbb906044016020604051808303816000875af1158015612535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612559919061307f565b5082602001516001600160a01b031683600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de866040516125a791815260200190565b60405180910390a350505050565b60008260020154600014806125d1575082600501548360020154145b61260757826005015483600201546125e991906130e1565b60038401546125f890876130b7565b612602919061310d565b612609565b845b905080158061261f5750670de0b6b3a764000085105b156126ae576126548460200151866121d27f000000000000000000000000000000000000000000000000000000000000000090565b83602001516001600160a01b031684600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de876040516126a191815260200190565b60405180910390a3612739565b8483600201546126be91906130ce565b600284015560038301546126d39082906130ce565b600384015581546126e59082906130ce565b82556020808501518551604080518981529384018590526001600160a01b039283169391909216917fcd0366dce5247d874ffc60a762aa7abbb82c1695bbb171609c1b8861e279eb73910160405180910390a35b5050505050565b6001600160a01b0381166000908152600e6020526040812060028101546001820154600483015492549192909161277791906130e1565b61278191906130e1565b610ad791906130e1565b6060600080846001600160a01b0316846040516127a89190613385565b600060405180830381855af49150503d80600081146127e3576040519150601f19603f3d011682016040523d82523d6000602084013e6127e8565b606091505b50915091506127f8858383612ae8565b95945050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000604051636dba849360e11b81526001600160a01b038581166004830152919091169063db750926906024016020604051808303816000875af115801561286e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289291906130f4565b9050806000036128a157505050565b60006128ad8383612b44565b905060006128bb82846130e1565b6001600160a01b038086166000908152601760205260409020549192506127399183918791161561234e565b6040516377561f0760e11b8152600481018290526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063eeac3e0e906024016020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad791906130f4565b600061298482620f4240101590565b82906129a657604051633dc311df60e01b815260040161023b91815260200190565b506129bd6129b783620f42406130e1565b84612a02565b610ad490846130e1565b80156120095760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401611f8e565b6000612a1183620f4240101590565b80612a245750612a2482620f4240101590565b83839091612a4e5760405163768bf0eb60e11b81526004810192909252602482015260440161023b565b50620f42409050612a5f83856130b7565b610ad4919061310d565b6001600160a01b0382166000908152600e6020526040902054612a8d9082906130ce565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290612adc9084815260200190565b60405180910390a25050565b606082612afd57612af882612bab565b610e78565b8151158015612b1457506001600160a01b0384163b155b15612b3d57604051639996b31560e01b81526001600160a01b038516600482015260240161023b565b5080610e78565b6001600160a01b0382166000908152601460205260408120600281015482919015801590612b8457508054640100000000900463ffffffff16620f424010155b156123465780546000906123219063ffffffff6401000000009091048116908790612a0216565b805115612bbb5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114612bd457600080fd5b60008060408385031215612bff57600080fd5b8235612c0a81612bd7565b91506020830135612c1a81612bd7565b809150509250929050565b600060208284031215612c3757600080fd5b8135610ad481612bd7565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151612cb060c084018263ffffffff169052565b5060e0830151612ccb60e08401826001600160401b03169052565b5092915050565b60008060408385031215612ce557600080fd5b8235612cf081612bd7565b946020939093013593505050565b600080600060608486031215612d1357600080fd5b8335612d1e81612bd7565b92506020840135612d2e81612bd7565b9150604084013560038110612d4257600080fd5b809150509250925092565b600080600060608486031215612d6257600080fd5b8335612d6d81612bd7565b92506020840135612d7d81612bd7565b9150604084013563ffffffff81168114612d4257600080fd5b60008060408385031215612da957600080fd5b823591506020830135612c1a81612bd7565b600080600060608486031215612dd057600080fd5b8335612ddb81612bd7565b92506020840135612deb81612bd7565b91506040840135612d4281612bd7565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612e3357634e487b7160e01b600052602160045260246000fd5b91905290565b60008083601f840112612e4b57600080fd5b5081356001600160401b03811115612e6257600080fd5b602083019150836020828501011115612e7a57600080fd5b9250929050565b600080600060408486031215612e9657600080fd5b8335612ea181612bd7565b925060208401356001600160401b03811115612ebc57600080fd5b612ec886828701612e39565b9497909650939450505050565b60008060008060608587031215612eeb57600080fd5b8435612ef681612bd7565b93506020850135925060408501356001600160401b03811115612f1857600080fd5b612f2487828801612e39565b95989497509550505050565b60008060208385031215612f4357600080fd5b82356001600160401b03811115612f5957600080fd5b8301601f81018513612f6a57600080fd5b80356001600160401b03811115612f8057600080fd5b8560208260051b8401011115612f9557600080fd5b6020919091019590945092505050565b60005b83811015612fc0578181015183820152602001612fa8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561303d57603f198786030184528151805180875261301a816020890160208501612fa5565b601f01601f19169590950160209081019550938401939190910190600101612ff1565b50929695505050505050565b60006020828403121561305b57600080fd5b5035919050565b60006020828403121561307457600080fd5b8151610ad481612bd7565b60006020828403121561309157600080fd5b81518015158114610ad457600080fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610ad757610ad76130a1565b80820180821115610ad757610ad76130a1565b81810381811115610ad757610ad76130a1565b60006020828403121561310657600080fd5b5051919050565b60008261312a57634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561319c5761319c61315e565b604052919050565b600080604083850312156131b757600080fd5b823560ff811681146131c857600080fd5b915060208301356001600160401b038111156131e357600080fd5b8301601f810185136131f457600080fd5b80356001600160401b0381111561320d5761320d61315e565b613220601f8201601f1916602001613174565b81815286602083850101111561323557600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000602082840312801561326857600080fd5b50604051602081016001600160401b038111828210171561328b5761328b61315e565b604052825161329981612bd7565b81529392505050565b600060408284031280156132b557600080fd5b50604080519081016001600160401b03811182821017156132d8576132d861315e565b60405282516132e681612bd7565b815260208301516132f681612bd7565b60208201529392505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261332f57600080fd5b8301803591506001600160401b0382111561334957600080fd5b602001915036819003821315612e7a57600080fd5b82848237600083820160008152835161337b818360208801612fa5565b0195945050505050565b60008251613397818460208701612fa5565b919091019291505056fea264697066735822122038ad83d20c219353421029f1ad8c4f7667d5f0e86af1579c64603bb56827d86064736f6c634300081b0033", + "linkReferences": { + "contracts/staking/libraries/ExponentialRebates.sol": { + "ExponentialRebates": [ + { + "length": 20, + "start": 5879 + } + ] + } + }, + "deployedLinkReferences": { + "contracts/staking/libraries/ExponentialRebates.sol": { + "ExponentialRebates": [ + { + "length": 20, + "start": 4455 + } + ] + } + } +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow.json new file mode 100644 index 000000000..4f10cc208 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow.json @@ -0,0 +1,769 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymentsEscrow", + "sourceName": "contracts/payments/PaymentsEscrow.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "revokeCollectorThawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawEscrowThawingPeriod", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balanceBefore", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInconsistentCollection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAllowance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBalance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowNotThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "PaymentsEscrowStillThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "thawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxThawingPeriod", + "type": "uint256" + } + ], + "name": "PaymentsEscrowThawingPeriodTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "AuthorizedCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "CancelThaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "CancelThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "EscrowCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "RevokeCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "Thaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "ThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVOKE_COLLECTOR_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WITHDRAW_ESCROW_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + } + ], + "name": "approveCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "authorizedCollectors", + "outputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "cancelThawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "escrowAccounts", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + } + ], + "name": "revokeCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "thawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b506040516120c73803806120c78339810160408190526100309161046b565b826001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b2906103a1565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e5906103a1565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e906103a1565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b6020820152610158906103a1565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b6020820152610190906103a1565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb906103a1565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b6020820152610209906103a1565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b6020820152610245906103a1565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a906103a1565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450816276a7008082111561035c57604051635c0f65a160e01b815260048101929092526024820152604401610071565b508190506276a7008082111561038e57604051635c0f65a160e01b815260048101929092526024820152604401610071565b50506101c0919091526101e05250610510565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103dc91815260200190565b602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d91906104a0565b9050826001600160a01b0382166104485760405163218f5add60e11b815260040161007191906104c2565b5092915050565b80516001600160a01b038116811461046657600080fd5b919050565b60008060006060848603121561048057600080fd5b6104898461044f565b602085015160409095015190969495509392505050565b6000602082840312156104b257600080fd5b6104bb8261044f565b9392505050565b602081526000825180602084015260005b818110156104f057602081860181015160408684010152016104d3565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051611ad26105f5600039600081816101e00152610abb015260008181610193015261039d01526000505060005050600050506000505060005050600081816102fa0152818161041601528181610589015281816106380152818161076e0152818161094901528181610b2d01528181610d71015261131b01526000505060008181610fa6015261104e015260005050600081816108da01528181610eea01528181610f77015281816110c401526114130152611ad26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json new file mode 100644 index 000000000..4f10cc208 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/PaymentsEscrow#PaymentsEscrow_Instance.json @@ -0,0 +1,769 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PaymentsEscrow", + "sourceName": "contracts/payments/PaymentsEscrow.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "controller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "revokeCollectorThawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawEscrowThawingPeriod", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balanceBefore", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInconsistentCollection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAllowance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBalance", + "type": "uint256" + } + ], + "name": "PaymentsEscrowInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowInvalidZeroTokens", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowIsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentsEscrowNotThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "PaymentsEscrowStillThawing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "thawingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxThawingPeriod", + "type": "uint256" + } + ], + "name": "PaymentsEscrowThawingPeriodTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "AuthorizedCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "CancelThaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "CancelThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "EscrowCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "RevokeCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "name": "Thaw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "ThawCollector", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVOKE_COLLECTOR_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WITHDRAW_ESCROW_THAWING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + } + ], + "name": "approveCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "authorizedCollectors", + "outputs": [ + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "cancelThawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "collect", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "escrowAccounts", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensThawing", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thawEndTimestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector_", + "type": "address" + } + ], + "name": "revokeCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "thaw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "thawCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x61020060405234801561001157600080fd5b506040516120c73803806120c78339810160408190526100309161046b565b826001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b2906103a1565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e5906103a1565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e906103a1565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b6020820152610158906103a1565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b6020820152610190906103a1565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb906103a1565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b6020820152610209906103a1565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b6020820152610245906103a1565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a906103a1565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450816276a7008082111561035c57604051635c0f65a160e01b815260048101929092526024820152604401610071565b508190506276a7008082111561038e57604051635c0f65a160e01b815260048101929092526024820152604401610071565b50506101c0919091526101e05250610510565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103dc91815260200190565b602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d91906104a0565b9050826001600160a01b0382166104485760405163218f5add60e11b815260040161007191906104c2565b5092915050565b80516001600160a01b038116811461046657600080fd5b919050565b60008060006060848603121561048057600080fd5b6104898461044f565b602085015160409095015190969495509392505050565b6000602082840312156104b257600080fd5b6104bb8261044f565b9392505050565b602081526000825180602084015260005b818110156104f057602081860181015160408684010152016104d3565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051611ad26105f5600039600081816101e00152610abb015260008181610193015261039d01526000505060005050600050506000505060005050600081816102fa0152818161041601528181610589015281816106380152818161076e0152818161094901528181610b2d01528181610d71015261131b01526000505060008181610fa6015261104e015260005050600081816108da01528181610eea01528181610f77015281816110c401526114130152611ad26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#GraphProxy.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#GraphProxy.json new file mode 100644 index 000000000..2cfb21e41 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#GraphProxy.json @@ -0,0 +1,177 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GraphProxy", + "sourceName": "contracts/upgrades/GraphProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "ImplementationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "PendingImplementationUpdated", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "acceptUpgradeAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newAdmin", + "type": "address" + } + ], + "name": "setAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c", + "deployedBytecode": "0x6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager.json new file mode 100644 index 000000000..87ac4c282 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager.json @@ -0,0 +1,635 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RewardsManager", + "sourceName": "contracts/rewards/RewardsManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardsAssigned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "RewardsDenied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sinceBlock", + "type": "uint256" + } + ], + "name": "RewardsDenylistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldSubgraphService", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [], + "name": "accRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accRewardsPerSignalLastBlockUpdated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "name": "calcRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "denylist", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsForSubgraph", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsPerAllocatedToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNewRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "getRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isDenied", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "issuancePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumSubgraphSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphAllocationUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphSignalUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "_deny", + "type": "bool" + } + ], + "name": "setDenied", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_subgraphDeploymentID", + "type": "bytes32[]" + }, + { + "internalType": "bool[]", + "name": "_deny", + "type": "bool[]" + } + ], + "name": "setDeniedMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_issuancePerBlock", + "type": "uint256" + } + ], + "name": "setIssuancePerBlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumSubgraphSignal", + "type": "uint256" + } + ], + "name": "setMinimumSubgraphSignal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphAvailabilityOracle", + "type": "address" + } + ], + "name": "setSubgraphAvailabilityOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphAvailabilityOracle", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "contract IRewardsIssuer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "subgraphs", + "outputs": [ + { + "internalType": "uint256", + "name": "accRewardsForSubgraph", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsForSubgraphSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerSignalSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "takeRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051611eb861017360003980610fe1525080610fb8525080610f8f528061194f525080610f6652806116d2525080610f3d525080610f14525080610eeb52806115165250611eb86000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager_Instance.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager_Instance.json new file mode 100644 index 000000000..87ac4c282 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/RewardsManager#RewardsManager_Instance.json @@ -0,0 +1,635 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RewardsManager", + "sourceName": "contracts/rewards/RewardsManager.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nameHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "param", + "type": "string" + } + ], + "name": "ParameterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardsAssigned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + } + ], + "name": "RewardsDenied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "subgraphDeploymentID", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sinceBlock", + "type": "uint256" + } + ], + "name": "RewardsDenylistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "name": "SetController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldSubgraphService", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newSubgraphService", + "type": "address" + } + ], + "name": "SubgraphServiceSet", + "type": "event" + }, + { + "inputs": [], + "name": "accRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accRewardsPerSignalLastBlockUpdated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + } + ], + "name": "acceptProxy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGraphProxy", + "name": "_proxy", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "acceptProxyAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "name": "calcRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "contract IController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "denylist", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsForSubgraph", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "getAccRewardsPerAllocatedToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNewRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "getRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "isDenied", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "issuancePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumSubgraphSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphAllocationUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + } + ], + "name": "onSubgraphSignalUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + } + ], + "name": "setController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_subgraphDeploymentID", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "_deny", + "type": "bool" + } + ], + "name": "setDenied", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_subgraphDeploymentID", + "type": "bytes32[]" + }, + { + "internalType": "bool[]", + "name": "_deny", + "type": "bool[]" + } + ], + "name": "setDeniedMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_issuancePerBlock", + "type": "uint256" + } + ], + "name": "setIssuancePerBlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumSubgraphSignal", + "type": "uint256" + } + ], + "name": "setMinimumSubgraphSignal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphAvailabilityOracle", + "type": "address" + } + ], + "name": "setSubgraphAvailabilityOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_subgraphService", + "type": "address" + } + ], + "name": "setSubgraphService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphAvailabilityOracle", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subgraphService", + "outputs": [ + { + "internalType": "contract IRewardsIssuer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "subgraphs", + "outputs": [ + { + "internalType": "uint256", + "name": "accRewardsForSubgraph", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsForSubgraphSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerSignalSnapshot", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardsPerAllocatedToken", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncAllContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_allocationID", + "type": "address" + } + ], + "name": "takeRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateAccRewardsPerSignal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051611eb861017360003980610fe1525080610fb8525080610f8f528061194f525080610f6652806116d2525080610f3d525080610f14525080610eeb52806115165250611eb86000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/artifacts/TAPCollector#TAPCollector.json b/packages/horizon/ignition/deployments/chain-421614/artifacts/TAPCollector#TAPCollector.json new file mode 100644 index 000000000..94f0189f7 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/artifacts/TAPCollector#TAPCollector.json @@ -0,0 +1,450 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TAPCollector", + "sourceName": "contracts/payments/collectors/TAPCollector.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "eip712Name", + "type": "string" + }, + { + "internalType": "string", + "name": "eip712Version", + "type": "string" + }, + { + "internalType": "address", + "name": "controller", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "contractName", + "type": "bytes" + } + ], + "name": "GraphDirectoryInvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "PPMMathInvalidMulPPM", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "dataService", + "type": "address" + } + ], + "name": "TAPCollectorCallerNotDataService", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensCollected", + "type": "uint256" + } + ], + "name": "TAPCollectorInconsistentRAVTokens", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "graphToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphStaking", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphPayments", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEscrow", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "graphController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphEpochManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphRewardsManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphTokenGateway", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphProxyAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "graphCuration", + "type": "address" + } + ], + "name": "GraphDirectoryInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensReceiver", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokensDataService", + "type": "uint256" + } + ], + "name": "PaymentCollected", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "enum IGraphPayments.PaymentTypes", + "name": "paymentType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "collect", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timestampNs", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "valueAggregate", + "type": "uint128" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "internalType": "struct ITAPCollector.ReceiptAggregateVoucher", + "name": "rav", + "type": "tuple" + } + ], + "name": "encodeRAV", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "address", + "name": "serviceProvider", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timestampNs", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "valueAggregate", + "type": "uint128" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "internalType": "struct ITAPCollector.ReceiptAggregateVoucher", + "name": "rav", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct ITAPCollector.SignedRAV", + "name": "signedRAV", + "type": "tuple" + } + ], + "name": "recoverRAVSigner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dataService", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "tokensCollected", + "outputs": [ + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6102a060405234801561001157600080fd5b506040516119ae3803806119ae833981016040819052610030916105d9565b80838361003e8260006103db565b6101205261004d8160016103db565b61014052815160208084019190912060e052815190820120610100524660a0526100da60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c0526001600160a01b03811661012c5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101e05260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526101649061040e565b6001600160a01b0316610160526040805180820190915260078152665374616b696e6760c81b60208201526101989061040e565b6001600160a01b03166101805260408051808201909152600d81526c47726170685061796d656e747360981b60208201526101d29061040e565b6001600160a01b03166101a05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261020d9061040e565b6001600160a01b03166101c05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b60208201526102469061040e565b6001600160a01b03166102005260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526102819061040e565b6001600160a01b0316610220526040805180820190915260118152704772617068546f6b656e4761746577617960781b60208201526102bf9061040e565b6001600160a01b03166102405260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b60208201526102fb9061040e565b6001600160a01b03166102605260408051808201909152600881526721bab930ba34b7b760c11b60208201526103309061040e565b6001600160a01b039081166102808190526101e05161018051610160516101a0516101c0516102005161022051610240516102605160408051968c168752948b166020870152928a1685850152908916606085015288166080840152871660a083015260c0820195909552935192851694918216939116917fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a439181900360e00190a45050505061081e565b60006020835110156103f7576103f0836104bc565b9050610408565b8161040284826106db565b5060ff90505b92915050565b6000806101e0516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161044991815260200190565b602060405180830381865afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a9190610799565b9050826001600160a01b0382166104b55760405163218f5add60e11b815260040161012391906107e7565b5092915050565b600080829050601f815111156104e7578260405163305a27a960e01b815260040161012391906107e7565b80516104f2826107fa565b179392505050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561052b578181015183820152602001610513565b50506000910152565b600082601f83011261054557600080fd5b81516001600160401b0381111561055e5761055e6104fa565b604051601f8201601f19908116603f011681016001600160401b038111828210171561058c5761058c6104fa565b6040528181528382016020018510156105a457600080fd5b6105b5826020830160208701610510565b949350505050565b80516001600160a01b03811681146105d457600080fd5b919050565b6000806000606084860312156105ee57600080fd5b83516001600160401b0381111561060457600080fd5b61061086828701610534565b602086015190945090506001600160401b0381111561062e57600080fd5b61063a86828701610534565b925050610649604085016105bd565b90509250925092565b600181811c9082168061066657607f821691505b60208210810361068657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156106d657806000526020600020601f840160051c810160208510156106b35750805b601f840160051c820191505b818110156106d357600081556001016106bf565b50505b505050565b81516001600160401b038111156106f4576106f46104fa565b610708816107028454610652565b8461068c565b6020601f82116001811461073c57600083156107245750848201515b600019600385901b1c1916600184901b1784556106d3565b600084815260208120601f198516915b8281101561076c578785015182556020948501946001909201910161074c565b508482101561078a5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6000602082840312156107ab57600080fd5b6107b4826105bd565b9392505050565b600081518084526107d3816020860160208601610510565b601f01601f19169290920160200192915050565b6020815260006107b460208301846107bb565b805160208083015191908110156106865760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516110e36108cb600039600050506000505060005050600050506000505060005050600061024f0152600050506000505060005050600061049201526000610460015260006108940152600061086c015260006107c7015260006107f10152600061081b01526110e36000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631ef518f21461005c5780637f07d2831461008c57806384b0196e146100ad5780638821603c146100c8578063cfdb35bd146100db575b600080fd5b61006f61006a3660046109dc565b61010c565b6040516001600160a01b0390911681526020015b60405180910390f35b61009f61009a366004610b23565b610125565b604051908152602001610083565b6100b5610372565b6040516100839796959493929190610bc6565b61009f6100d6366004610c5e565b6103b8565b61009f6100e9366004610cb0565b600260209081526000938452604080852082529284528284209052825290205481565b600061011f61011a83610db8565b6103cb565b92915050565b60008060008380602001905181019061013e9190610e75565b815151919350915033906001600160a01b0381168214610189576040516347666ba360e11b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b50508151516000610199846103cb565b84516020808201516060909201516001600160a01b038087166000908152600284526040808220838716835285528082209287168252919093529091205492935090916001600160801b03909116908181808211610213576040516308e467d960e31b815260048101929092526024820152604401610180565b50600090506102228284610fb1565b9050600061023082896103f2565b905081156102f3576040516343edff4160e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906387dbfe829061028e908f908a908a9088908e908990600401610fda565b600060405180830381600087803b1580156102a857600080fd5b505af11580156102bc573d6000803e3d6000fd5b5050506001600160a01b0380891660009081526002602090815260408083208a851684528252808320938b16835292905220859055505b866001600160a01b0316866001600160a01b03168d600281111561031957610319610fc4565b604080516001600160a01b038a168152602081018790529081018590527ffadd34108e3c00b000a046b272ee080bb1755b91078c0ef5200c0b7da6132bd19060600160405180910390a4509a9950505050505050505050565b600060608060008060006060610386610459565b61038e61048b565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b600061011f6103c68361102e565b6104b8565b6000806103db83600001516104b8565b90506103eb81846020015161056f565b9392505050565b600061040183620f4240101590565b80610414575061041482620f4240101590565b8383909161043e5760405163768bf0eb60e11b815260048101929092526024820152604401610180565b50620f4240905061044f838561103a565b6103eb9190611051565b60606104867f00000000000000000000000000000000000000000000000000000000000000006000610599565b905090565b60606104867f00000000000000000000000000000000000000000000000000000000000000006001610599565b600061011f7fe502a96d6aaed328ceacc76a5f627b9823162f5a205dab5a702b40073a6778428360000151846020015185604001518660600151876080015180519060200120604051602001610554969594939291909586526001600160a01b0394851660208701529290931660408501526001600160401b031660608401526001600160801b0391909116608083015260a082015260c00190565b60405160208183030381529060405280519060200120610644565b60008060008061057f8686610671565b92509250925061058f82826106be565b5090949350505050565b606060ff83146105b3576105ac8361077b565b905061011f565b8180546105bf90611073565b80601f01602080910402602001604051908101604052809291908181526020018280546105eb90611073565b80156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b5050505050905061011f565b600061011f6106516107ba565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600083516041036106ab5760208401516040850151606086015160001a61069d888285856108e5565b9550955095505050506106b7565b50508151600091506002905b9250925092565b60008260038111156106d2576106d2610fc4565b036106db575050565b60018260038111156106ef576106ef610fc4565b0361070d5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561072157610721610fc4565b036107425760405163fce698f760e01b815260048101829052602401610180565b600382600381111561075657610756610fc4565b03610777576040516335e2f38360e21b815260048101829052602401610180565b5050565b60606000610788836109b4565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561081357507f000000000000000000000000000000000000000000000000000000000000000046145b1561083d57507f000000000000000000000000000000000000000000000000000000000000000090565b610486604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561092057506000915060039050826109aa565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610974573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109a0575060009250600191508290506109aa565b9250600091508190505b9450945094915050565b600060ff8216601f81111561011f57604051632cd44ac360e21b815260040160405180910390fd5b6000602082840312156109ee57600080fd5b81356001600160401b03811115610a0457600080fd5b8201604081850312156103eb57600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610a4e57610a4e610a16565b60405290565b604080519081016001600160401b0381118282101715610a4e57610a4e610a16565b604051601f8201601f191681016001600160401b0381118282101715610a9e57610a9e610a16565b604052919050565b60006001600160401b03821115610abf57610abf610a16565b50601f01601f191660200190565b600082601f830112610ade57600080fd5b8135610af1610aec82610aa6565b610a76565b818152846020838601011115610b0657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215610b3657600080fd5b823560038110610b4557600080fd5b915060208301356001600160401b03811115610b6057600080fd5b610b6c85828601610acd565b9150509250929050565b60005b83811015610b91578181015183820152602001610b79565b50506000910152565b60008151808452610bb2816020860160208601610b76565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e060208201526000610be560e0830189610b9a565b8281036040840152610bf78189610b9a565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b81811015610c4d578351835260209384019390920191600101610c2f565b50909b9a5050505050505050505050565b600060208284031215610c7057600080fd5b81356001600160401b03811115610c8657600080fd5b820160a081850312156103eb57600080fd5b6001600160a01b0381168114610cad57600080fd5b50565b600080600060608486031215610cc557600080fd5b8335610cd081610c98565b92506020840135610ce081610c98565b91506040840135610cf081610c98565b809150509250925092565b6001600160401b0381168114610cad57600080fd5b6001600160801b0381168114610cad57600080fd5b600060a08284031215610d3757600080fd5b610d3f610a2c565b90508135610d4c81610c98565b81526020820135610d5c81610c98565b60208201526040820135610d6f81610cfb565b60408201526060820135610d8281610d10565b606082015260808201356001600160401b03811115610da057600080fd5b610dac84828501610acd565b60808301525092915050565b600060408236031215610dca57600080fd5b610dd2610a54565b82356001600160401b03811115610de857600080fd5b610df436828601610d25565b82525060208301356001600160401b03811115610e1057600080fd5b610e1c36828601610acd565b60208301525092915050565b600082601f830112610e3957600080fd5b8151610e47610aec82610aa6565b818152846020838601011115610e5c57600080fd5b610e6d826020830160208701610b76565b949350505050565b60008060408385031215610e8857600080fd5b82516001600160401b03811115610e9e57600080fd5b830160408186031215610eb057600080fd5b610eb8610a54565b81516001600160401b03811115610ece57600080fd5b820160a08188031215610ee057600080fd5b610ee8610a2c565b8151610ef381610c98565b81526020820151610f0381610c98565b60208201526040820151610f1681610cfb565b60408201526060820151610f2981610d10565b606082015260808201516001600160401b03811115610f4757600080fd5b610f5389828501610e28565b60808301525082525060208201516001600160401b03811115610f7557600080fd5b610f8187828501610e28565b602083810191909152959095015190969095509350505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011f5761011f610f9b565b634e487b7160e01b600052602160045260246000fd5b60c0810160038810610ffc57634e487b7160e01b600052602160045260246000fd5b9681526001600160a01b03958616602082015293851660408501526060840192909252909216608082015260a0015290565b600061011f3683610d25565b808202811582820484141761011f5761011f610f9b565b60008261106e57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061108757607f821691505b6020821081036110a757634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212204ea11b7f590e7303a0b1850b4cd59148c357bb48498bdb2606c6e97c057012e264736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80631ef518f21461005c5780637f07d2831461008c57806384b0196e146100ad5780638821603c146100c8578063cfdb35bd146100db575b600080fd5b61006f61006a3660046109dc565b61010c565b6040516001600160a01b0390911681526020015b60405180910390f35b61009f61009a366004610b23565b610125565b604051908152602001610083565b6100b5610372565b6040516100839796959493929190610bc6565b61009f6100d6366004610c5e565b6103b8565b61009f6100e9366004610cb0565b600260209081526000938452604080852082529284528284209052825290205481565b600061011f61011a83610db8565b6103cb565b92915050565b60008060008380602001905181019061013e9190610e75565b815151919350915033906001600160a01b0381168214610189576040516347666ba360e11b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b50508151516000610199846103cb565b84516020808201516060909201516001600160a01b038087166000908152600284526040808220838716835285528082209287168252919093529091205492935090916001600160801b03909116908181808211610213576040516308e467d960e31b815260048101929092526024820152604401610180565b50600090506102228284610fb1565b9050600061023082896103f2565b905081156102f3576040516343edff4160e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906387dbfe829061028e908f908a908a9088908e908990600401610fda565b600060405180830381600087803b1580156102a857600080fd5b505af11580156102bc573d6000803e3d6000fd5b5050506001600160a01b0380891660009081526002602090815260408083208a851684528252808320938b16835292905220859055505b866001600160a01b0316866001600160a01b03168d600281111561031957610319610fc4565b604080516001600160a01b038a168152602081018790529081018590527ffadd34108e3c00b000a046b272ee080bb1755b91078c0ef5200c0b7da6132bd19060600160405180910390a4509a9950505050505050505050565b600060608060008060006060610386610459565b61038e61048b565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b600061011f6103c68361102e565b6104b8565b6000806103db83600001516104b8565b90506103eb81846020015161056f565b9392505050565b600061040183620f4240101590565b80610414575061041482620f4240101590565b8383909161043e5760405163768bf0eb60e11b815260048101929092526024820152604401610180565b50620f4240905061044f838561103a565b6103eb9190611051565b60606104867f00000000000000000000000000000000000000000000000000000000000000006000610599565b905090565b60606104867f00000000000000000000000000000000000000000000000000000000000000006001610599565b600061011f7fe502a96d6aaed328ceacc76a5f627b9823162f5a205dab5a702b40073a6778428360000151846020015185604001518660600151876080015180519060200120604051602001610554969594939291909586526001600160a01b0394851660208701529290931660408501526001600160401b031660608401526001600160801b0391909116608083015260a082015260c00190565b60405160208183030381529060405280519060200120610644565b60008060008061057f8686610671565b92509250925061058f82826106be565b5090949350505050565b606060ff83146105b3576105ac8361077b565b905061011f565b8180546105bf90611073565b80601f01602080910402602001604051908101604052809291908181526020018280546105eb90611073565b80156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b5050505050905061011f565b600061011f6106516107ba565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600083516041036106ab5760208401516040850151606086015160001a61069d888285856108e5565b9550955095505050506106b7565b50508151600091506002905b9250925092565b60008260038111156106d2576106d2610fc4565b036106db575050565b60018260038111156106ef576106ef610fc4565b0361070d5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561072157610721610fc4565b036107425760405163fce698f760e01b815260048101829052602401610180565b600382600381111561075657610756610fc4565b03610777576040516335e2f38360e21b815260048101829052602401610180565b5050565b60606000610788836109b4565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561081357507f000000000000000000000000000000000000000000000000000000000000000046145b1561083d57507f000000000000000000000000000000000000000000000000000000000000000090565b610486604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561092057506000915060039050826109aa565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610974573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109a0575060009250600191508290506109aa565b9250600091508190505b9450945094915050565b600060ff8216601f81111561011f57604051632cd44ac360e21b815260040160405180910390fd5b6000602082840312156109ee57600080fd5b81356001600160401b03811115610a0457600080fd5b8201604081850312156103eb57600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610a4e57610a4e610a16565b60405290565b604080519081016001600160401b0381118282101715610a4e57610a4e610a16565b604051601f8201601f191681016001600160401b0381118282101715610a9e57610a9e610a16565b604052919050565b60006001600160401b03821115610abf57610abf610a16565b50601f01601f191660200190565b600082601f830112610ade57600080fd5b8135610af1610aec82610aa6565b610a76565b818152846020838601011115610b0657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215610b3657600080fd5b823560038110610b4557600080fd5b915060208301356001600160401b03811115610b6057600080fd5b610b6c85828601610acd565b9150509250929050565b60005b83811015610b91578181015183820152602001610b79565b50506000910152565b60008151808452610bb2816020860160208601610b76565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e060208201526000610be560e0830189610b9a565b8281036040840152610bf78189610b9a565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b81811015610c4d578351835260209384019390920191600101610c2f565b50909b9a5050505050505050505050565b600060208284031215610c7057600080fd5b81356001600160401b03811115610c8657600080fd5b820160a081850312156103eb57600080fd5b6001600160a01b0381168114610cad57600080fd5b50565b600080600060608486031215610cc557600080fd5b8335610cd081610c98565b92506020840135610ce081610c98565b91506040840135610cf081610c98565b809150509250925092565b6001600160401b0381168114610cad57600080fd5b6001600160801b0381168114610cad57600080fd5b600060a08284031215610d3757600080fd5b610d3f610a2c565b90508135610d4c81610c98565b81526020820135610d5c81610c98565b60208201526040820135610d6f81610cfb565b60408201526060820135610d8281610d10565b606082015260808201356001600160401b03811115610da057600080fd5b610dac84828501610acd565b60808301525092915050565b600060408236031215610dca57600080fd5b610dd2610a54565b82356001600160401b03811115610de857600080fd5b610df436828601610d25565b82525060208301356001600160401b03811115610e1057600080fd5b610e1c36828601610acd565b60208301525092915050565b600082601f830112610e3957600080fd5b8151610e47610aec82610aa6565b818152846020838601011115610e5c57600080fd5b610e6d826020830160208701610b76565b949350505050565b60008060408385031215610e8857600080fd5b82516001600160401b03811115610e9e57600080fd5b830160408186031215610eb057600080fd5b610eb8610a54565b81516001600160401b03811115610ece57600080fd5b820160a08188031215610ee057600080fd5b610ee8610a2c565b8151610ef381610c98565b81526020820151610f0381610c98565b60208201526040820151610f1681610cfb565b60408201526060820151610f2981610d10565b606082015260808201516001600160401b03811115610f4757600080fd5b610f5389828501610e28565b60808301525082525060208201516001600160401b03811115610f7557600080fd5b610f8187828501610e28565b602083810191909152959095015190969095509350505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011f5761011f610f9b565b634e487b7160e01b600052602160045260246000fd5b60c0810160038810610ffc57634e487b7160e01b600052602160045260246000fd5b9681526001600160a01b03958616602082015293851660408501526060840192909252909216608082015260a0015290565b600061011f3683610d25565b808202811582820484141761011f5761011f610f9b565b60008261106e57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061108757607f821691505b6020821081036110a757634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212204ea11b7f590e7303a0b1850b4cd59148c357bb48498bdb2606c6e97c057012e264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/packages/horizon/ignition/deployments/chain-421614/deployed_addresses.json b/packages/horizon/ignition/deployments/chain-421614/deployed_addresses.json new file mode 100644 index 000000000..28984fbe8 --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/deployed_addresses.json @@ -0,0 +1,41 @@ +{ + "BridgeEscrow#BridgeEscrow": "0xbC846a82491A4b6Ee5fd841c60923019d99F6D0c", + "Curation#Curation": "0x73A09b3A9C5531da3374A12a1282e40C3e2B7FA0", + "Curation#GraphCurationToken": "0xF1c0D12b4b4f6f0d66CE0A18A16876c9ca6D2E92", + "EpochManager#EpochManager": "0x039B22cEd4cDbF6Cd153F38ba7ae2731471e0542", + "GraphProxyAdmin#GraphProxyAdmin": "0x0eb1325d7F1a188D5914fddb8566aE513A28D0da", + "GraphToken#GraphToken": "0x21Ee267Efe20A7E846964D3f9E28F7e81d72547e", + "HorizonProxies#OZProxyDummy_GraphPayments": "0x60eE16fc2C4729343C7B3Ab9B322b2C6CcfbC681", + "HorizonStakingExtension#ExponentialRebates": "0x5Ab8e4eDb2d068C9c1ab9c96bfb3abCAb96e1534", + "RewardsManager#RewardsManager": "0xE7ed8F3e83a10a74CBfaDdC7596CBb79c4eccA17", + "Controller#Controller": "0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa", + "GraphTokenGateway#GraphTokenGateway": "0x2f3f6fbAD807800da2d1ABC9c949c45Bc1C81541", + "HorizonProxies#OZProxyDummy_PaymentsEscrow": "0xF39FD65373870fcb5868F7458d8d84485E5Bf890", + "HorizonProxies#TransparentUpgradeableProxy_GraphPayments": "0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f", + "HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow": "0x5904ab9c7806FCC7634F1DcDBec544eEa7490634", + "BridgeEscrow#GraphProxy": "0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79", + "Curation#GraphProxy": "0x4594A5915B3AAa78CdF6273a76678855Ca675860", + "GraphTokenGateway#GraphProxy": "0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D", + "RewardsManager#GraphProxy": "0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75", + "EpochManager#GraphProxy": "0x7975475801BEf845f10Ce7784DC69aB1e0344f11", + "GraphToken#GraphProxy": "0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702", + "BridgeEscrow#BridgeEscrow_Instance": "0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79", + "Curation#Curation_Instance": "0x4594A5915B3AAa78CdF6273a76678855Ca675860", + "EpochManager#EpochManager_Instance": "0x7975475801BEf845f10Ce7784DC69aB1e0344f11", + "GraphToken#GraphToken_Instance": "0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702", + "GraphTokenGateway#GraphTokenGateway_Instance": "0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D", + "HorizonProxies#ProxyAdmin_GraphPayments": "0xbb29b876AA2faCEb3af83d768CB03dd3BFF03f5e", + "HorizonProxies#ProxyAdmin_PaymentsEscrow": "0x6D892d831196E1Ad3779B97320b7091dE7d45053", + "RewardsManager#RewardsManager_Instance": "0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75", + "GraphHorizon_Periphery#Dummy": "0x3141000ae37361a525863D5cc4886799ed3FAFca", + "HorizonProxies#GraphProxy_HorizonStaking": "0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf", + "HorizonProxies#RegisteredDummy": "0xbDc6798b71a3B57fc79eF346d065de7477D3c366", + "GraphPayments#GraphPayments": "0xf5B3661BbB8CD48571C7f41ba2D896a3589C9753", + "GraphPayments#GraphPayments_Instance": "0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f", + "HorizonStakingExtension#HorizonStakingExtension": "0xf203161Ba7e25263deB79a4478BE18644C2c5446", + "PaymentsEscrow#PaymentsEscrow": "0x09B985a2042848A08bA59060EaF0f07c6F5D4d54", + "PaymentsEscrow#PaymentsEscrow_Instance": "0x5904ab9c7806FCC7634F1DcDBec544eEa7490634", + "TAPCollector#TAPCollector": "0xacC71844EF6beEF70106ABe6E51013189A1f3738", + "HorizonStaking#HorizonStaking": "0xFf2Ee30de92F276018642A59Fb7Be95b3F9088Af", + "HorizonStaking#HorizonStaking_Instance": "0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf" +} diff --git a/packages/horizon/ignition/deployments/chain-421614/journal.jsonl b/packages/horizon/ignition/deployments/chain-421614/journal.jsonl new file mode 100644 index 000000000..4a141ae3a --- /dev/null +++ b/packages/horizon/ignition/deployments/chain-421614/journal.jsonl @@ -0,0 +1,328 @@ + +{"chainId":421614,"type":"DEPLOYMENT_INITIALIZE"} +{"artifactId":"BridgeEscrow#BridgeEscrow","constructorArgs":[],"contractName":"BridgeEscrow","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"BridgeEscrow#BridgeEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"BridgeEscrow#BridgeEscrow","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051610c376101696000398061071f5250806106f65250806106cd528061089e5250806106a452508061067b5250806106525250806106295250610c376000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c4d66de81161005b578063c4d66de814610181578063d6866ea5146101a7578063e7dd4b2c146101af578063f77c4791146101d557610088565b80630621472c1461008d57806392eefe9b146100b55780639ce7abe5146100db578063a2594d821461015b575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101f9565b005b6100b3600480360360208110156100cb57600080fd5b50356001600160a01b0316610290565b6100b3600480360360408110156100f157600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561011c57600080fd5b82018360208201111561012e57600080fd5b8035906020019184600183028401116401000000008311171561015057600080fd5b5090925090506102a4565b6100b36004803603602081101561017157600080fd5b50356001600160a01b03166103fa565b6100b36004803603602081101561019757600080fd5b50356001600160a01b0316610515565b6100b3610624565b6100b3600480360360208110156101c557600080fd5b50356001600160a01b0316610745565b6101dd6107ac565b604080516001600160a01b039092168252519081900360200190f35b6102016107c1565b610209610897565b6001600160a01b031663095ea7b3826000196040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b505af1158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b505050565b6102986108c7565b6102a18161092c565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d602081101561030a57600080fd5b50516001600160a01b03163314610368576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156103dc57600080fd5b505af11580156103f0573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561043657600080fd5b505af115801561044a573d6000803e3d6000fd5b505050506040513d602081101561046057600080fd5b50516001600160a01b031633146104be576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104f957600080fd5b505af115801561050d573d6000803e3d6000fd5b505050505050565b61051d6109de565b6001600160a01b0316336001600160a01b031614610578576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600054610100900460ff16806105915750610591610a03565b8061059f575060005460ff16155b6105da5760405162461bcd60e51b815260040180806020018281038252602e815260200180610bd4602e913960400191505060405180910390fd5b600054610100900460ff16158015610605576000805460ff1961ff0019909116610100171660011790555b61060e82610298565b8015610620576000805461ff00191690555b5050565b61064d7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106767f0000000000000000000000000000000000000000000000000000000000000000610a14565b61069f7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106c87f0000000000000000000000000000000000000000000000000000000000000000610a14565b6106f17f0000000000000000000000000000000000000000000000000000000000000000610a14565b61071a7f0000000000000000000000000000000000000000000000000000000000000000610a14565b6107437f0000000000000000000000000000000000000000000000000000000000000000610a14565b565b61074d6107c1565b610755610897565b6001600160a01b031663095ea7b38260006040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561026157600080fd5b6000546201000090046001600160a01b031681565b600060029054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561080f57600080fd5b505afa158015610823573d6000803e3d6000fd5b505050506040513d602081101561083957600080fd5b50516001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006108c27f0000000000000000000000000000000000000000000000000000000000000000610b22565b905090565b6000546201000090046001600160a01b03163314610743576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610980576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b03831662010000810262010000600160b01b03199092169190911790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000610a0e30610bcd565b15905090565b60008060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146106205760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600160205260408120546001600160a01b031680610bc757600060029054906101000a90046001600160a01b03166001600160a01b031663f7641a5e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d6020811015610bc257600080fd5b505190505b92915050565b3b15159056fe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220db5bf6ed6a6394146ce0c6f8770a20ad4f778d16c74558284981457141097a0964736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"BridgeEscrow#BridgeEscrow","networkInteractionId":1,"nonce":540,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x13d14bc11804dbf49f9614ddaf091128170eb3f476918525d3446c48cfac26f7"},"type":"TRANSACTION_SEND"} +{"futureId":"BridgeEscrow#BridgeEscrow","hash":"0x13d14bc11804dbf49f9614ddaf091128170eb3f476918525d3446c48cfac26f7","networkInteractionId":1,"receipt":{"blockHash":"0x4e6a2163bf85dcff071956d9f18d3946b741934e1b5fabbe19eb0827f306d0f6","blockNumber":82177277,"contractAddress":"0xbC846a82491A4b6Ee5fd841c60923019d99F6D0c","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"BridgeEscrow#BridgeEscrow","result":{"address":"0xbC846a82491A4b6Ee5fd841c60923019d99F6D0c","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"Controller#Controller","constructorArgs":[],"contractName":"Controller","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"Controller#Controller","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Controller#Controller","networkInteraction":{"data":"0x608060405234801561001057600080fd5b506100243361003360201b6109b21760201c565b61002e6001610055565b6100e7565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff1615158115151415610075576100e4565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff910416156100a157426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a15b50565b610ba0806100f66000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80636cda3798116100a2578063e0e9929211610071578063e0e9929214610215578063e3056a3414610241578063eb5dd94f14610249578063f2fde38b14610275578063f7641a5e1461029b5761010b565b80636cda3798146101ce57806379ba5097146101e85780639181df9c146101f057806391b4ded91461020d5761010b565b806348bde20c116100de57806348bde20c146101795780634fc07d751461019f57806356371bd8146101a75780635c975abb146101c65761010b565b80630c340a241461011057806316c38b3c1461013457806324a3d622146101555780632e292fc71461015d575b600080fd5b6101186102b8565b604080516001600160a01b039092168252519081900360200190f35b6101536004803603602081101561014a57600080fd5b503515156102c7565b005b610118610331565b610165610340565b604080519115158252519081900360200190f35b6101536004803603602081101561018f57600080fd5b50356001600160a01b0316610350565b61011861040c565b610153600480360360208110156101bd57600080fd5b5035151561041b565b610165610482565b6101d6610492565b60408051918252519081900360200190f35b610153610498565b6101536004803603602081101561020657600080fd5b50356105a6565b6101d6610651565b6101536004803603604081101561022b57600080fd5b50803590602001356001600160a01b0316610657565b61011861076e565b6101536004803603604081101561025f57600080fd5b50803590602001356001600160a01b031661077d565b6101536004803603602081101561028b57600080fd5b50356001600160a01b0316610899565b610118600480360360208110156102b157600080fd5b5035610997565b6000546001600160a01b031681565b6000546001600160a01b03163314806102ea57506004546001600160a01b031633145b6103255760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e816109d4565b50565b6004546001600160a01b031681565b600154600160a01b900460ff1690565b6000546001600160a01b031633146103a8576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610403576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b61032e81610a65565b6000546001600160a01b031690565b6000546001600160a01b031633148061043e57506004546001600160a01b031633145b6104795760405162461bcd60e51b8152600401808060200182810382526022815260200180610b496022913960400191505060405180910390fd5b61032e81610ab7565b600154600160a81b900460ff1690565b60025481565b6001546001600160a01b031680158015906104bb5750336001600160a01b038216145b61050c576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b600081815260056020908152604080832080546001600160a01b031916905580519283525183927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a250565b60035481565b6000546001600160a01b031633146106af576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661070a576040805162461bcd60e51b815260206004820152601c60248201527f436f6e74726163742061646472657373206d7573742062652073657400000000604482015290519081900360640190fd5b60008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927f937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd92908290030190a25050565b6001546001600160a01b031681565b6000546001600160a01b031633146107d5576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610829576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b6000828152600560205260408082205481516392eefe9b60e01b81526001600160a01b038581166004830152925192909116926392eefe9b9260248084019382900301818387803b15801561087d57600080fd5b505af1158015610891573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146108f1576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610943576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000908152600560205260409020546001600160a01b031690565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600160159054906101000a900460ff16151581151514156109f45761032e565b6001805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615610a2057426003555b60015460408051600160a81b90920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b600160149054906101000a900460ff1615158115151415610ad75761032e565b6001805460ff60a01b1916600160a01b8315158102919091179182905560ff91041615610b0357426002555b60015460408051600160a01b90920460ff1615158252517f511b770d1b1dc5cbd412a5017f55cbb2295b826385e5f46c1de2b6ebeb44ae02916020908290030190a15056fe4f6e6c7920476f7665726e6f72206f7220477561726469616e2063616e2063616c6ca2646970667358221220c742dbbf8f38fda928d26053c584788bb7d7b003131594b9e14f1381ebbdbb3064736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Controller#Controller","networkInteractionId":1,"nonce":541,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x22f6e912acc9d7888fadcb3b37c4989b24c418547984408f34feccaad11edaab"},"type":"TRANSACTION_SEND"} +{"artifactId":"Curation#Curation","constructorArgs":[],"contractName":"Curation","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"Curation#Curation","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#Curation","networkInteraction":{"data":"0x6101806040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea361014052613d0960e61b6101605234801561011a57600080fd5b5060805160a05160c05160e0516101005161012051610140516101605160e01c6128cc61018f60003980610c2f52508061141b52806119025250806113f25250806113c9528061180c5250806113a05280611dbf5250806113775280611ff252508061134e52508061132552506128cc6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806399439fee11610104578063cd0ad4a2116100a2578063eff1d50e11610071578063eff1d50e146103f2578063f049b900146103fa578063f115c4271461040d578063f77c479114610415576101da565b8063cd0ad4a2146103af578063cd18119e146103c2578063d6866ea5146103d5578063eba0c8a1146103dd576101da565b80639f94c667116100de5780639f94c6671461035f578063a2594d8214610372578063a25e62c714610385578063b5217bb41461038d576101da565b806399439fee146103265780639b4d9f33146103395780639ce7abe51461034c576101da565b80634c4ea0ed1161017c5780637a2a45b81161014b5780637a2a45b8146102da57806381573288146102ed57806392eefe9b1461030057806393a90a1e14610313576101da565b80634c4ea0ed1461027f5780634c8c7a441461029f5780636536fe32146102b457806369db11a1146102c7576101da565b806326058249116101b857806326058249146102235780633718896d14610238578063375a54ab1461024b57806346e855da1461026c576101da565b80630faaf87f146101df578063185360f91461020857806324bdeec714610210575b600080fd5b6101f26101ed366004612175565b61041d565b6040516101ff91906122ab565b60405180910390f35b6101f26104da565b6101f261021e366004612196565b6104e0565b61022b610662565b6040516101ff9190612273565b6101f2610246366004612175565b610677565b61025e610259366004612196565b6108b6565b6040516101ff9291906127b8565b6101f261027a36600461215d565b610af7565b61029261028d36600461215d565b610b0c565b6040516101ff91906122a0565b6102b26102ad3660046120e4565b610b20565b005b6102b26102c236600461215d565b610cb0565b6101f26102d5366004612175565b610cc4565b6101f26102e8366004612175565b610d78565b6102b26102fb366004612175565b610d8b565b6102b261030e3660046120c8565b610e5e565b6102b26103213660046120c8565b610e6f565b6101f261033436600461215d565b610ecb565b6102b26103473660046120c8565b610f72565b6102b261035a3660046121c1565b610f83565b6101f261036d366004612132565b6110d9565b6102b26103803660046120c8565b61118d565b61022b6112a8565b6103a061039b36600461215d565b6112be565b6040516101ff939291906127dc565b6102b26103bd366004612259565b6112ef565b6102b26103d0366004612259565b61130f565b6102b2611320565b6103e5611441565b6040516101ff9190612801565b61022b611454565b61025e610408366004612175565b611463565b6103e56114c0565b61022b6114cc565b6000828152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b0316908201528161046d85610ecb565b82519091506104975760405162461bcd60e51b815260040161048e906125e8565b60405180910390fd5b838110156104b75760405162461bcd60e51b815260040161048e906124f3565b81516104cf9082906104c990876114db565b90611534565b925050505b92915050565b600d5481565b60006104ea61159b565b33836105085760405162461bcd60e51b815260040161048e906122b4565b8361051382876110d9565b10156105315760405162461bcd60e51b815260040161048e906124af565b600061053d868661041d565b90508381101561055f5760405162461bcd60e51b815260040161048e906123ff565b61056886611709565b6000868152600f60205260409020805461058290836117a8565b8155600181015460405163079cc67960e41b8152600160201b9091046001600160a01b0316906379cc6790906105be9086908a90600401612287565b600060405180830381600087803b1580156105d857600080fd5b505af11580156105ec573d6000803e3d6000fd5b505050506105f987610ecb565b61060257600081555b61061461060d611805565b8484611835565b86836001600160a01b03167fe14cd5e80f6821ded0538e85a537487acf10bb5e97a12176df56a099e90bfb3484896040516106509291906127b8565b60405180910390a35095945050505050565b6010546201000090046001600160a01b031681565b600061068161159b565b6106896118fb565b6001600160a01b0316336001600160a01b0316146106b95760405162461bcd60e51b815260040161048e90612781565b816106d65760405162461bcd60e51b815260040161048e906126c0565b60006106e28484611926565b6000858152600f6020526040902090915033906106fe86610b0c565b6107ca576001810154600160201b90046001600160a01b03166107ca57600c5460009061073a90600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610769903090600401612273565b600060405180830381600087803b15801561078357600080fd5b505af1158015610797573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6107d386611709565b60006107dd611805565b90506107ea818488611a76565b81546107f69087611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f19906108329086908890600401612287565b600060405180830381600087803b15801561084c57600080fd5b505af1158015610860573d6000803e3d6000fd5b5050505086836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf888760006040516108a3939291906127c6565b60405180910390a3509195945050505050565b6000806108c161159b565b836108de5760405162461bcd60e51b815260040161048e906126c0565b6000806108eb8787611463565b915091508482101561090f5760405162461bcd60e51b815260040161048e906123ff565b6000878152600f60205260409020339061092889610b0c565b6109f4576001810154600160201b90046001600160a01b03166109f457600c5460009061096490600160401b90046001600160a01b03166119d9565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890610993903090600401612273565b600060405180830381600087803b1580156109ad57600080fd5b505af11580156109c1573d6000803e3d6000fd5b5050506001830180546001600160a01b03909316600160201b02640100000000600160c01b031990931692909217909155505b6109fd89611709565b6000610a07611805565b9050610a1481848b611a76565b610a1e8185611b2f565b610a33610a2b8a866117a8565b835490611ad5565b825560018201546040516340c10f1960e01b8152600160201b9091046001600160a01b0316906340c10f1990610a6f9086908990600401612287565b600060405180830381600087803b158015610a8957600080fd5b505af1158015610a9d573d6000803e3d6000fd5b5050505089836001600160a01b03167fb7bf5f4e5b23ef992df9875ecea572620d18dab0c1a5486a9b695d20d9ec50cf8b8888604051610adf939291906127c6565b60405180910390a35092989197509095505050505050565b6000818152600f60205260409020545b919050565b6000908152600f6020526040902054151590565b610b28611b7b565b6001600160a01b0316336001600160a01b031614610b83576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b601054610100900460ff1680610b9c5750610b9c611ba0565b80610baa575060105460ff16155b610be55760405162461bcd60e51b815260040180806020018281038252602e815260200180612848602e913960400191505060405180910390fd5b601054610100900460ff16158015610c10576010805460ff1961ff0019909116610100171660011790555b610c1985610e66565b600c805467ffffffff000000001916600160201b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff160217905560405160008051602061282883398151915290610c74906123d2565b60405180910390a1610c8583611bb1565b610c8e82611c16565b610c9784611c54565b8015610ca9576010805461ff00191690555b5050505050565b610cb8611ce4565b610cc181611c16565b50565b600081610ce35760405162461bcd60e51b815260040161048e90612322565b6000610cef8484611926565b6000858152600f6020908152604080832081516060810183528154815260019091015463ffffffff811693820193909352600160201b9092046001600160a01b031690820152919250610d4b83610d4588610ecb565b90611ad5565b8251909150600090610d5d9087611ad5565b9050610d6d826104c983876114db565b979650505050505050565b6000610d848383611926565b9392505050565b6010546201000090046001600160a01b0316331480610dc25750610dad611db8565b6001600160a01b0316336001600160a01b0316145b610dde5760405162461bcd60e51b815260040161048e9061255c565b610de782610b0c565b610e035760405162461bcd60e51b815260040161048e9061245c565b6000828152600f602052604090208054610e1d9083611ad5565b815560405183907ff17fdee613a92b35db6b7598eb43750b24d4072eb304e6eca80121e40402e34b90610e519085906122ab565b60405180910390a2505050565b610e66611de3565b610cc181611e42565b610e77611ce4565b6010805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517f81dcb738da3dabd5bb2adbc7dd107fbbfca936e9c8aecab25f5b17a710a784c790600090a250565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015610f6957806001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2c57600080fd5b505afa158015610f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f649190612241565b610d84565b60009392505050565b610f7a611ce4565b610cc181611c54565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050506040513d6020811015610fe957600080fd5b50516001600160a01b03163314611047576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b1580156110bb57600080fd5b505af11580156110cf573d6000803e3d6000fd5b5050505050505050565b6000818152600f6020526040812060010154600160201b90046001600160a01b03168015611182576040516370a0823160e01b81526001600160a01b038216906370a082319061112d908790600401612273565b60206040518083038186803b15801561114557600080fd5b505afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612241565b611185565b60005b949350505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c957600080fd5b505af11580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b50516001600160a01b03163314611251576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b505050505050565b600c54600160401b90046001600160a01b031681565b600f602052600090815260409020805460019091015463ffffffff811690600160201b90046001600160a01b031683565b6112f7611ce4565b60405162461bcd60e51b815260040161048e906123a3565b611317611ce4565b610cc181611bb1565b6113497f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113727f0000000000000000000000000000000000000000000000000000000000000000611eea565b61139b7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113c47f0000000000000000000000000000000000000000000000000000000000000000611eea565b6113ed7f0000000000000000000000000000000000000000000000000000000000000000611eea565b6114167f0000000000000000000000000000000000000000000000000000000000000000611eea565b61143f7f0000000000000000000000000000000000000000000000000000000000000000611eea565b565b600c54600160201b900463ffffffff1681565b600e546001600160a01b031681565b600c546000908190819061149790620f4240906104c990879061149190849063ffffffff908116906117a816565b906114db565b905060006114a585836117a8565b905060006114b38784611926565b9791965090945050505050565b600c5463ffffffff1681565b6000546001600160a01b031681565b6000826114ea575060006104d4565b828202828482816114f757fe5b0414610d845760405162461bcd60e51b81526004018080602001828103825260218152602001806128766021913960400191505060405180910390fd5b600080821161158a576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161159357fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b50511561164e576040805162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b604482015290519081900360640190fd5b60008054906101000a90046001600160a01b03166001600160a01b0316632e292fc76040518163ffffffff1660e01b815260040160206040518083038186803b15801561169a57600080fd5b505afa1580156116ae573d6000803e3d6000fd5b505050506040513d60208110156116c457600080fd5b50511561143f576040805162461bcd60e51b815260206004820152600e60248201526d14185c9d1a585b0b5c185d5cd95960921b604482015290519081900360640190fd5b6000611713611feb565b90506001600160a01b038116156117a4576040516307470bfb60e21b81526001600160a01b03821690631d1c2fec906117509085906004016122ab565b602060405180830381600087803b15801561176a57600080fd5b505af115801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190612241565b505b5050565b6000828211156117ff576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b905090565b80156117a257826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561189257600080fd5b505af11580156118a6573d6000803e3d6000fd5b505050506040513d60208110156118bc57600080fd5b50516117a2576040805162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000828152600f602090815260408083208151606081018352815480825260019092015463ffffffff811694820194909452600160201b9093046001600160a01b0316918301919091526119c657600d548310156119965760405162461bcd60e51b815260040161048e90612359565b600d546119be906119b6906104c96119ae87836117a8565b6001906114db565b600190611ad5565b9150506104d4565b8051611185906104c98561149188610ecb565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116610b07576040805162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b604482015290519081900360640190fd5b80156117a257604080516323b872dd60e01b81526001600160a01b038481166004830152306024830152604482018490529151918516916323b872dd916064808201926020929091908290030181600087803b15801561189257600080fd5b600082820183811015610d84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b80156117a457816001600160a01b03166342966c68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561128c57600080fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611bab306120ae565b15905090565b620f424063ffffffff82161115611bda5760405162461bcd60e51b815260040161048e906126f7565b600c805463ffffffff191663ffffffff831617905560405160008051602061282883398151915290611c0b906125b9565b60405180910390a150565b80611c335760405162461bcd60e51b815260040161048e90612645565b600d81905560405160008051602061282883398151915290611c0b9061242c565b6001600160a01b038116611c7a5760405162461bcd60e51b815260040161048e906122eb565b611c83816120ae565b611c9f5760405162461bcd60e51b815260040161048e90612689565b600c805468010000000000000000600160e01b031916600160401b6001600160a01b0384160217905560405160008051602061282883398151915290611c0b90612754565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015611d3057600080fd5b505afa158015611d44573d6000803e3d6000fd5b505050506040513d6020811015611d5a57600080fd5b50516001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b60006118307f0000000000000000000000000000000000000000000000000000000000000000612012565b6000546001600160a01b0316331461143f576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116611e96576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146117a45760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b60006118307f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b0316806104d45760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561207b57600080fd5b505afa15801561208f573d6000803e3d6000fd5b505050506040513d60208110156120a557600080fd5b50519392505050565b3b151590565b803563ffffffff81168114610b0757600080fd5b6000602082840312156120d9578081fd5b8135610d8481612812565b600080600080608085870312156120f9578283fd5b843561210481612812565b9350602085013561211481612812565b9250612122604086016120b4565b9396929550929360600135925050565b60008060408385031215612144578182fd5b823561214f81612812565b946020939093013593505050565b60006020828403121561216e578081fd5b5035919050565b60008060408385031215612187578182fd5b50508035926020909101359150565b6000806000606084860312156121aa578283fd5b505081359360208301359350604090920135919050565b6000806000604084860312156121d5578283fd5b83356121e081612812565b9250602084013567ffffffffffffffff808211156121fc578384fd5b818601915086601f83011261220f578384fd5b81358181111561221d578485fd5b87602082850101111561222e578485fd5b6020830194508093505050509250925092565b600060208284031215612252578081fd5b5051919050565b60006020828403121561226a578081fd5b610d84826120b4565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b60208082526017908201527f43616e6e6f74206275726e207a65726f207369676e616c000000000000000000604082015260600190565b6020808252601e908201527f546f6b656e206d6173746572206d757374206265206e6f6e2d656d7074790000604082015260600190565b6020808252601d908201527f43616e27742063616c63756c6174652077697468203020746f6b656e73000000604082015260600190565b6020808252602a908201527f4375726174696f6e206465706f7369742069732062656c6f77206d696e696d756040820152691b481c995c5d5a5c995960b21b606082015260800190565b6020808252601590820152742737ba1034b6b83632b6b2b73a32b21034b710261960591b604082015260600190565b60208082526013908201527264656661756c7452657365727665526174696f60681b604082015260600190565b60208082526013908201527229b634b83830b3b290383937ba32b1ba34b7b760691b604082015260600190565b6020808252601690820152751b5a5b9a5b5d5b50dd5c985d1a5bdb91195c1bdcda5d60521b604082015260600190565b60208082526033908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527274656420746f20636f6c6c656374206665657360681b606082015260800190565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207369676e616c207468616e20796f756040820152631037bbb760e11b606082015260800190565b60208082526043908201527f5369676e616c206d7573742062652061626f7665206f7220657175616c20746f60408201527f207369676e616c2069737375656420696e20746865206375726174696f6e20706060820152621bdbdb60ea1b608082015260a00190565b60208082526037908201527f43616c6c6572206d75737420626520746865207375626772617068207365727660408201527f696365206f72207374616b696e6720636f6e7472616374000000000000000000606082015260800190565b6020808252601590820152746375726174696f6e54617850657263656e7461676560581b604082015260600190565b6020808252603b908201527f5375626772617068206465706c6f796d656e74206d757374206265206375726160408201527f74656420746f20706572666f726d2063616c63756c6174696f6e730000000000606082015260800190565b60208082526024908201527f4d696e696d756d206375726174696f6e206465706f7369742063616e6e6f74206040820152630626520360e41b606082015260800190565b6020808252601f908201527f546f6b656e206d6173746572206d757374206265206120636f6e747261637400604082015260600190565b6020808252601a908201527f43616e6e6f74206465706f736974207a65726f20746f6b656e73000000000000604082015260600190565b60208082526039908201527f4375726174696f6e207461782070657263656e74616765206d7573742062652060408201527f62656c6f77206f7220657175616c20746f204d41585f50504d00000000000000606082015260800190565b60208082526013908201527231bab930ba34b7b72a37b5b2b726b0b9ba32b960691b604082015260600190565b6020808252601a908201527f4f6e6c792074686520474e532063616e2063616c6c2074686973000000000000604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b92835263ffffffff9190911660208301526001600160a01b0316604082015260600190565b63ffffffff91909116815260200190565b6001600160a01b0381168114610cc157600080fdfe96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a1d7866b5729d907dd1710f966a8454930b048b6c785a4ad687a5e1b7a901ea164736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#Curation","networkInteractionId":1,"nonce":542,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x8f68c53238685f6e265aa509796a8eb579bef8ffe53ff6e3b7bcf42f099bcbe3"},"type":"TRANSACTION_SEND"} +{"futureId":"Curation#Curation","hash":"0x8f68c53238685f6e265aa509796a8eb579bef8ffe53ff6e3b7bcf42f099bcbe3","networkInteractionId":1,"receipt":{"blockHash":"0x953c311a7d515cf400dc15d21805d69060e4861943ad7f473bc653a9595880b8","blockNumber":82177307,"contractAddress":"0x73A09b3A9C5531da3374A12a1282e40C3e2B7FA0","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#Curation","result":{"address":"0x73A09b3A9C5531da3374A12a1282e40C3e2B7FA0","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"Curation#GraphCurationToken","constructorArgs":[],"contractName":"GraphCurationToken","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"Curation#GraphCurationToken","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#GraphCurationToken","networkInteraction":{"data":"0x608060405234801561001057600080fd5b506114ec806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806379ba5097116100a2578063a9059cbb11610071578063a9059cbb14610352578063c4d66de81461037e578063dd62ed3e146103a4578063e3056a34146103d2578063f2fde38b146103da57610116565b806379ba5097146102ea57806379cc6790146102f257806395d89b411461031e578063a457c2d71461032657610116565b806323b872dd116100e957806323b872dd14610216578063313ce5671461024c578063395093511461026a57806340c10f191461029657806370a08231146102c457610116565b806306fdde031461011b578063095ea7b3146101985780630c340a24146101d857806318160ddd146101fc575b600080fd5b610123610400565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015d578181015183820152602001610145565b50505050905090810190601f16801561018a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c4600480360360408110156101ae57600080fd5b506001600160a01b038135169060200135610496565b604080519115158252519081900360200190f35b6101e06104b3565b604080516001600160a01b039092168252519081900360200190f35b6102046104c2565b60408051918252519081900360200190f35b6101c46004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356104c8565b61025461054f565b6040805160ff9092168252519081900360200190f35b6101c46004803603604081101561028057600080fd5b506001600160a01b038135169060200135610558565b6102c2600480360360408110156102ac57600080fd5b506001600160a01b0381351690602001356105a6565b005b610204600480360360208110156102da57600080fd5b50356001600160a01b031661060c565b6102c2610627565b6102c26004803603604081101561030857600080fd5b506001600160a01b038135169060200135610737565b610123610799565b6101c46004803603604081101561033c57600080fd5b506001600160a01b0381351690602001356107fa565b6101c46004803603604081101561036857600080fd5b506001600160a01b038135169060200135610862565b6102c26004803603602081101561039457600080fd5b50356001600160a01b0316610876565b610204600480360360408110156103ba57600080fd5b506001600160a01b0381358116916020013516610972565b6101e061099d565b6102c2600480360360208110156103f057600080fd5b50356001600160a01b03166109ac565b60368054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b820191906000526020600020905b81548152906001019060200180831161046f57829003601f168201915b5050505050905090565b60006104aa6104a3610aaa565b8484610aae565b50600192915050565b6065546001600160a01b031681565b60355490565b60006104d5848484610b9a565b610545846104e1610aaa565b61054085604051806060016040528060288152602001611400602891396001600160a01b038a1660009081526034602052604081209061051f610aaa565b6001600160a01b031681526020810191909152604001600020549190610cf7565b610aae565b5060019392505050565b60385460ff1690565b60006104aa610565610aaa565b846105408560346000610576610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610d8e565b6065546001600160a01b031633146105fe576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610def565b5050565b6001600160a01b031660009081526033602052604090205490565b6066546001600160a01b0316801580159061064a5750336001600160a01b038216145b61069b576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b606580546001600160a01b038381166001600160a01b0319808416919091179384905560668054909116905560405191811692169082907f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f90600090a36066546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6065546001600160a01b0316331461078f576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6106088282610ee1565b60378054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561048c5780601f106104615761010080835404028352916020019161048c565b60006104aa610807610aaa565b84610540856040518060600160405280602581526020016114926025913960346000610831610aaa565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610cf7565b60006104aa61086f610aaa565b8484610b9a565b600054610100900460ff168061088f575061088f610fdd565b8061089d575060005460ff16155b6108d85760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015610903576000805460ff1961ff0019909116610100171660011790555b61090c82610fee565b61095d604051806040016040528060148152602001734772617068204375726174696f6e20536861726560601b8152506040518060400160405280600381526020016247435360e81b815250611010565b8015610608576000805461ff00191690555050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6066546001600160a01b031681565b6065546001600160a01b03163314610a04576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610a56576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b606680546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b038316610af35760405162461bcd60e51b815260040180806020018281038252602481526020018061146e6024913960400191505060405180910390fd5b6001600160a01b038216610b385760405162461bcd60e51b815260040180806020018281038252602281526020018061138a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610bdf5760405162461bcd60e51b81526004018080602001828103825260258152602001806114496025913960400191505060405180910390fd5b6001600160a01b038216610c245760405162461bcd60e51b81526004018080602001828103825260238152602001806113456023913960400191505060405180910390fd5b610c2f8383836110c1565b610c6c816040518060600160405280602681526020016113ac602691396001600160a01b0386166000908152603360205260409020549190610cf7565b6001600160a01b038085166000908152603360205260408082209390935590841681522054610c9b9082610d8e565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610d865760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d4b578181015183820152602001610d33565b50505050905090810190601f168015610d785780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610de8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610e4a576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610e56600083836110c1565b603554610e639082610d8e565b6035556001600160a01b038216600090815260336020526040902054610e899082610d8e565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610f265760405162461bcd60e51b81526004018080602001828103825260218152602001806114286021913960400191505060405180910390fd5b610f32826000836110c1565b610f6f81604051806060016040528060228152602001611368602291396001600160a01b0385166000908152603360205260409020549190610cf7565b6001600160a01b038316600090815260336020526040902055603554610f9590826110c6565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6000610fe830611123565b15905090565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16806110295750611029610fdd565b80611037575060005460ff16155b6110725760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff1615801561109d576000805460ff1961ff0019909116610100171660011790555b6110a5611129565b6110af83836111cb565b80156110c1576000805461ff00191690555b505050565b60008282111561111d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600054610100900460ff16806111425750611142610fdd565b80611150575060005460ff16155b61118b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff161580156111b6576000805460ff1961ff0019909116610100171660011790555b80156111c8576000805461ff00191690555b50565b600054610100900460ff16806111e457506111e4610fdd565b806111f2575060005460ff16155b61122d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806113d2602e913960400191505060405180910390fd5b600054610100900460ff16158015611258576000805460ff1961ff0019909116610100171660011790555b825161126b9060369060208601906112a3565b50815161127f9060379060208501906112a3565b506038805460ff1916601217905580156110c1576000805461ff0019169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826112d9576000855561131f565b82601f106112f257805160ff191683800117855561131f565b8280016001018555821561131f579182015b8281111561131f578251825591602001919060010190611304565b5061132b92915061132f565b5090565b5b8082111561132b576000815560010161133056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212200b687fddcd01dbad6e1d5fbd49cb041f69ed61684a12a4c26c6e37e0f5ad7c2a64736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#GraphCurationToken","networkInteractionId":1,"nonce":543,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xb5b516edbce5e30c09e2733b297aa9249e2319643e15264a1267abf097540d2d"},"type":"TRANSACTION_SEND"} +{"futureId":"Curation#GraphCurationToken","hash":"0xb5b516edbce5e30c09e2733b297aa9249e2319643e15264a1267abf097540d2d","networkInteractionId":1,"receipt":{"blockHash":"0x9c76d371c53140ff322e94744093507c5b8e8a4b69dc92857f68f5bede691dc4","blockNumber":82177320,"contractAddress":"0xF1c0D12b4b4f6f0d66CE0A18A16876c9ca6D2E92","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#GraphCurationToken","result":{"address":"0xF1c0D12b4b4f6f0d66CE0A18A16876c9ca6D2E92","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"EpochManager#EpochManager","constructorArgs":[],"contractName":"EpochManager","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"EpochManager#EpochManager","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"EpochManager#EpochManager","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161103461016460003980610aac525080610a83525080610a5a525080610a31525080610a085250806109df5250806109b652506110346000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a2594d82116100ad578063cd6dc68711610071578063cd6dc687146102c4578063d0cfa46e146102f0578063d6866ea5146102f8578063f77c479114610300578063faa1a23c146103245761012c565b8063a2594d821461027e578063ab93122c146102a4578063b4146a0b146102ac578063c46e58eb146102b4578063cc65149b146102bc5761012c565b806376671808116100f457806376671808146101ab57806385df51fd146101b35780638ae63d6d146101d057806392eefe9b146101d85780639ce7abe5146101fe5761012c565b806319c3b82d146101315780631b28126d1461014b5780631ce05d381461016857806354eea7961461018457806357d775f8146101a3575b600080fd5b61013961032c565b60408051918252519081900360200190f35b6101396004803603602081101561016157600080fd5b5035610353565b61017061037f565b604080519115158252519081900360200190f35b6101a16004803603602081101561019a57600080fd5b5035610392565b005b61013961047f565b610139610485565b610139600480360360208110156101c957600080fd5b503561049b565b61013961053b565b6101a1600480360360208110156101ee57600080fd5b50356001600160a01b031661053f565b6101a16004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b509092509050610553565b6101a16004803603602081101561029457600080fd5b50356001600160a01b03166106a9565b6101396107c4565b6101396107e6565b6101a16107ec565b610139610888565b6101a1600480360360408110156102da57600080fd5b506001600160a01b03813516906020013561088e565b610139610999565b6101a16109b1565b610308610ad2565b604080516001600160a01b039092168252519081900360200190f35b610139610ae1565b600061034e600c54610348600f5461034261053b565b90610ae7565b90610b49565b905090565b60008061035e610485565b905080831061036e576000610378565b6103788184610ae7565b9392505050565b6000610389610485565b600d5414905090565b61039a610bb0565b600081116103ea576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b600c5481141561042b5760405162461bcd60e51b8152600401808060200182810382526029815260200180610f666029913960400191505060405180910390fd5b610433610485565b600e5561043e6107c4565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a250565b600c5481565b600061034e61049261032c565b600e5490610c84565b6000806104a661053b565b90508083106104e65760405162461bcd60e51b8152600401808060200182810382526023815260200180610fdc6023913960400191505060405180910390fd5b6101008110806104fa575061010081038310155b6105355760405162461bcd60e51b815260040180806020018281038252602c815260200180610fb0602c913960400191505060405180910390fd5b50504090565b4390565b610547610cde565b61055081610d3d565b50565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b505050506040513d60208110156105b957600080fd5b50516001600160a01b03163314610617576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561068b57600080fd5b505af115801561069f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156106e557600080fd5b505af11580156106f9573d6000803e3d6000fd5b505050506040513d602081101561070f57600080fd5b50516001600160a01b0316331461076d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050505050565b600061034e6107dd600c546107d761032c565b90610de5565b600f5490610c84565b600e5481565b6107f461037f565b15610846576040805162461bcd60e51b815260206004820152601960248201527f43757272656e742065706f636820616c72656164792072756e00000000000000604482015290519081900360640190fd5b61084e610485565b600d8190556040805133815290517f666a37ccc682d20f8c51c5f6fd835cbadbcaaf09921e076282446e42d7264e3e9181900360200190a2565b600f5481565b610896610e3e565b6001600160a01b0316336001600160a01b0316146108f1576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b60008111610941576040805162461bcd60e51b8152602060048201526018602482015277045706f6368206c656e6774682063616e6e6f7420626520360441b604482015290519081900360640190fd5b61094a82610547565b6001600e5561095761053b565b600f55600c819055600e546040805183815290517f25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce24419181900360200190a25050565b60006109a36107c4565b6109ab61053b565b03905090565b6109da7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a037f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a2c7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a557f0000000000000000000000000000000000000000000000000000000000000000610e63565b610a7e7f0000000000000000000000000000000000000000000000000000000000000000610e63565b610aa77f0000000000000000000000000000000000000000000000000000000000000000610e63565b610ad07f0000000000000000000000000000000000000000000000000000000000000000610e63565b565b6000546001600160a01b031681565b600d5481565b600082821115610b3e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000808211610b9f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610ba857fe5b049392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bfc57600080fd5b505afa158015610c10573d6000803e3d6000fd5b505050506040513d6020811015610c2657600080fd5b50516001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b600082820183811015610378576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b03163314610ad0576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b038116610d91576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600082610df457506000610b43565b82820282848281610e0157fe5b04146103785760405162461bcd60e51b8152600401808060200182810382526021815260200180610f8f6021913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50516000838152600160205260409020549091506001600160a01b03808316911614610f615760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25b505056fe45706f6368206c656e677468206d75737420626520646966666572656e7420746f2063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e206f6e6c792072657472696576652068617368657320666f72206c6173742032353620626c6f636b7343616e206f6e6c79207265747269657665207061737420626c6f636b20686173686573a264697066735822122047006a21e84412eeff168d7feb465a4b7993ba048471f600407dddbf9d425b4764736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"EpochManager#EpochManager","networkInteractionId":1,"nonce":544,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xdfd7ab6b622201f1fdc28ee9efe48e408474e67f4cdc9b851750816ccb8fdc48"},"type":"TRANSACTION_SEND"} +{"futureId":"EpochManager#EpochManager","hash":"0xdfd7ab6b622201f1fdc28ee9efe48e408474e67f4cdc9b851750816ccb8fdc48","networkInteractionId":1,"receipt":{"blockHash":"0x4ed62d906394e8babe15813de784b6b9a645a8ddc7d59d0b4b937bacb8faee5b","blockNumber":82177335,"contractAddress":"0x039B22cEd4cDbF6Cd153F38ba7ae2731471e0542","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"EpochManager#EpochManager","result":{"address":"0x039B22cEd4cDbF6Cd153F38ba7ae2731471e0542","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphProxyAdmin#GraphProxyAdmin","constructorArgs":[],"contractName":"GraphProxyAdmin","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"GraphProxyAdmin#GraphProxyAdmin","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","networkInteraction":{"data":"0x608060405234801561001057600080fd5b506100243361002960201b610a0c1760201c565b61004b565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610a648061005a6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80637eff275e116100715780637eff275e146101b157806399a88ec4146101df578063e3056a341461020d578063eb451a0214610215578063f2fde38b14610243578063f3b7dead14610269576100a9565b806307ebde0e146100ae5780630c340a2414610139578063204e1c7a1461015d5780635bf410eb1461018357806379ba5097146101a9575b600080fd5b610137600480360360608110156100c457600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156100f857600080fd5b82018360208201111561010a57600080fd5b8035906020019184600183028401116401000000008311171561012c57600080fd5b50909250905061028f565b005b610141610388565b604080516001600160a01b039092168252519081900360200190f35b6101416004803603602081101561017357600080fd5b50356001600160a01b0316610397565b6101416004803603602081101561019957600080fd5b50356001600160a01b031661046a565b610137610525565b610137600480360360408110156101c757600080fd5b506001600160a01b0381358116916020013516610633565b610137600480360360408110156101f557600080fd5b506001600160a01b03813581169160200135166106f6565b61014161079d565b6101376004803603604081101561022b57600080fd5b506001600160a01b03813581169160200135166107ac565b6101376004803603602081101561025957600080fd5b50356001600160a01b0316610853565b6101416004803603602081101561027f57600080fd5b50356001600160a01b0316610951565b6000546001600160a01b031633146102e7576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b836001600160a01b0316639ce7abe58484846040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b15801561036a57600080fd5b505af115801561037e573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031681565b6000806000836001600160a01b03166040518080635c60da1b60e01b8152506004019050600060405180830381855afa9150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b50915091508161044b576040805162461bcd60e51b8152602060048201526016602482015275141c9bde1e481a5b5c1b0818d85b1b0819985a5b195960521b604482015290519081900360640190fd5b80806020019051602081101561046057600080fd5b5051949350505050565b6000806000836001600160a01b0316604051808063396f7b2360e01b8152506004019050600060405180830381855afa9150503d80600081146104c9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ce565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601d60248201527f50726f78792070656e64696e67496d706c2063616c6c206661696c6564000000604482015290519081900360640190fd5b6001546001600160a01b031680158015906105485750336001600160a01b038216145b610599576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000546001600160a01b0316331461068b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663704b6c02826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b505af11580156106ee573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461074e576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b0316633659cfe6826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6001546001600160a01b031681565b6000546001600160a01b03163314610804576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b816001600160a01b031663a2594d82826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156106da57600080fd5b6000546001600160a01b031633146108ab576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b0381166108fd576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000806000836001600160a01b031660405180806303e1469160e61b8152506004019050600060405180830381855afa9150503d80600081146109b0576040519150601f19603f3d011682016040523d82523d6000602084013e6109b5565b606091505b50915091508161044b576040805162461bcd60e51b815260206004820152601760248201527f50726f78792061646d696e2063616c6c206661696c6564000000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b039290921691909117905556fea26469706673582212208b271ee4c7625d89f662c15e90f70e142245bf56f0595043fe9af742b09d958c64736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","networkInteractionId":1,"nonce":545,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x22a237b3b519d594d6d2f4c18440328ecc586f6eaba8f98cf74236d49679f6e2"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","hash":"0x22a237b3b519d594d6d2f4c18440328ecc586f6eaba8f98cf74236d49679f6e2","networkInteractionId":1,"receipt":{"blockHash":"0x598b54b384d008d77e508bfc62782ae2b6719ad7bd5a8cd1095da17ff079e2ce","blockNumber":82177351,"contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin","result":{"address":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphToken#GraphToken","constructorArgs":[],"contractName":"GraphToken","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"GraphToken#GraphToken","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken","networkInteraction":{"data":"0x6101206040527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726080527fefcec85968da792893fa503eb21730083fc6c50ed5461e56163b28335b2a5f9660a0527f044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d60c0527fe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f565959160e0527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610100523480156100c657600080fd5b5060805160a05160c05160e0516101005161261e61010660003980611547525080611eae525080611e5e525080611e3d525080611e1c525061261e6000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638c2a993e1161011a578063a9059cbb116100ad578063ca52d7d71161007c578063ca52d7d71461067a578063d505accf146106a0578063dd62ed3e146106f1578063e3056a341461071f578063f2fde38b14610727576101fb565b8063a9059cbb146105fa578063aa271e1a14610626578063c2eeeebd1461064c578063c4d66de814610654576101fb565b806398650275116100e957806398650275146105205780639ce7abe514610528578063a2594d82146105a8578063a457c2d7146105ce576101fb565b80638c2a993e146104a057806390646b4a146104cc57806395d89b41146104f2578063983b2d56146104fa576101fb565b8063395093511161019257806374f4f5471161016157806374f4f5471461041a57806379ba50971461044657806379cc67901461044e5780637ecebe001461047a576101fb565b8063395093511461037f57806340c10f19146103ab57806342966c68146103d757806370a08231146103f4576101fb565b806318160ddd116101ce57806318160ddd146102e957806323b872dd146103035780633092afd514610339578063313ce56714610361576101fb565b806306fdde0314610200578063095ea7b31461027d5780630c340a24146102bd578063116191b6146102e1575b600080fd5b61020861074d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561024257818101518382015260200161022a565b50505050905090810190601f16801561026f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102a96004803603604081101561029357600080fd5b506001600160a01b0381351690602001356107e3565b604080519115158252519081900360200190f35b6102c5610800565b604080516001600160a01b039092168252519081900360200190f35b6102c561080f565b6102f161081e565b60408051918252519081900360200190f35b6102a96004803603606081101561031957600080fd5b506001600160a01b03813581169160208101359091169060400135610824565b61035f6004803603602081101561034f57600080fd5b50356001600160a01b03166108ab565b005b610369610958565b6040805160ff9092168252519081900360200190f35b6102a96004803603604081101561039557600080fd5b506001600160a01b038135169060200135610961565b61035f600480360360408110156103c157600080fd5b506001600160a01b0381351690602001356109af565b61035f600480360360208110156103ed57600080fd5b5035610a0e565b6102f16004803603602081101561040a57600080fd5b50356001600160a01b0316610a1f565b61035f6004803603604081101561043057600080fd5b506001600160a01b038135169060200135610a3a565b61035f610ad4565b61035f6004803603604081101561046457600080fd5b506001600160a01b038135169060200135610be2565b6102f16004803603602081101561049057600080fd5b50356001600160a01b0316610c3c565b61035f600480360360408110156104b657600080fd5b506001600160a01b038135169060200135610c4e565b61035f600480360360208110156104e257600080fd5b50356001600160a01b0316610ce8565b610208610de1565b61035f6004803603602081101561051057600080fd5b50356001600160a01b0316610e42565b61035f610eef565b61035f6004803603604081101561053e57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561056957600080fd5b82018360208201111561057b57600080fd5b8035906020019184600183028401116401000000008311171561059d57600080fd5b509092509050610f43565b61035f600480360360208110156105be57600080fd5b50356001600160a01b0316611099565b6102a9600480360360408110156105e457600080fd5b506001600160a01b0381351690602001356111b4565b6102a96004803603604081101561061057600080fd5b506001600160a01b03813516906020013561121c565b6102a96004803603602081101561063c57600080fd5b50356001600160a01b0316611230565b6102c561124e565b61035f6004803603602081101561066a57600080fd5b50356001600160a01b031661125d565b61035f6004803603602081101561069057600080fd5b50356001600160a01b03166113d3565b61035f600480360360e08110156106b657600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356114cf565b6102f16004803603604081101561070757600080fd5b506001600160a01b0381358116916020013516611680565b6102c56116ab565b61035f6004803603602081101561073d57600080fd5b50356001600160a01b03166116ba565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b820191906000526020600020905b8154815290600101906020018083116107bc57829003601f168201915b5050505050905090565b60006107f76107f06117b8565b84846117bc565b50600192915050565b6000546001600160a01b031681565b60ca546001600160a01b031681565b60365490565b60006108318484846118a8565b6108a18461083d6117b8565b61089c8560405180606001604052806028815260200161250e602891396001600160a01b038a1660009081526035602052604081209061087b6117b8565b6001600160a01b031681526020810191909152604001600020549190611a05565b6117bc565b5060019392505050565b6000546001600160a01b03163314610903576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b61090c81611230565b61094c576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b61095581611a9c565b50565b60395460ff1690565b60006107f761096e6117b8565b8461089c856035600061097f6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611ae5565b6109b833611230565b610a00576040805162461bcd60e51b815260206004820152601460248201527313db9b1e481b5a5b9d195c8818d85b8818d85b1b60621b604482015290519081900360640190fd5b610a0a8282611b46565b5050565b610955610a196117b8565b82611c38565b6001600160a01b031660009081526034602052604090205490565b60ca546001600160a01b03163314610a87576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610a918282610be2565b6040805182815290516001600160a01b038416917fe87aeeb22c5753db7f543198a4c3089d2233040ea9d1cab0eaa3b96d94d4fc6e919081900360200190a25050565b6001546001600160a01b03168015801590610af75750336001600160a01b038216145b610b48576040805162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206d7573742062652070656e64696e6720676f7665726e6f7200604482015290519081900360640190fd5b600080546001600160a01b038381166001600160a01b031980841691909117808555600180549092169091556040519282169391169183917f0ac6deed30eef60090c749850e10f2fa469e3e25fec1d1bef2853003f6e6f18f91a36001546040516001600160a01b03918216918416907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b6000610c198260405180606001604052806024815260200161253660249139610c1286610c0d6117b8565b611680565b9190611a05565b9050610c2d83610c276117b8565b836117bc565b610c378383611c38565b505050565b609a6020526000908152604090205481565b60ca546001600160a01b03163314610c9b576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f4741544557415960a81b604482015290519081900360640190fd5b610ca58282611b46565b6040805182815290516001600160a01b038416917fae4b6e741e38054ad6705655cc56c91c184f6768f76b41e10803e2766d89e19f919081900360200190a25050565b6000546001600160a01b03163314610d40576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610d8d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4741544557415960881b604482015290519081900360640190fd5b60ca80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5317fa585931182194fed99f2ea5f2efd38af9cff9724273704c8501c521e34b9181900360200190a150565b60388054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107d95780601f106107ae576101008083540402835291602001916107d9565b6000546001600160a01b03163314610e9a576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116610ee6576040805162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa6a4a72a22a960911b604482015290519081900360640190fd5b61095581611d34565b610ef833611230565b610f38576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa0afa6a4a72a22a960a11b604482015290519081900360640190fd5b610f4133611a9c565b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f7f57600080fd5b505af1158015610f93573d6000803e3d6000fd5b505050506040513d6020811015610fa957600080fd5b50516001600160a01b03163314611007576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b15801561107b57600080fd5b505af115801561108f573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b50516001600160a01b0316331461115d576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561119857600080fd5b505af11580156111ac573d6000803e3d6000fd5b505050505050565b60006107f76111c16117b8565b8461089c856040518060600160405280602581526020016125c460259139603560006111eb6117b8565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611a05565b60006107f76112296117b8565b84846118a8565b6001600160a01b031660009081526099602052604090205460ff1690565b60cb546001600160a01b031681565b611265611d80565b6001600160a01b0316336001600160a01b0316146112c0576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b600154600160a81b900460ff16806112db57506112db611da5565b806112f05750600154600160a01b900460ff16155b61132b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015611362576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b6001600160a01b0382166113b1576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b6113bc826000611db6565b8015610a0a576001805460ff60a81b191690555050565b6000546001600160a01b0316331461142b576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b03811661147b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f4c315f4144445245535360701b604482015290519081900360640190fd5b60cb80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f603c0b2e4494ac82839a70be8b6c660d7d042ccfe71c3ce0e5157f59090e74459181900360200190a150565b8315806114dc5750834211155b611523576040805162461bcd60e51b815260206004820152601360248201527211d4950e88195e1c1a5c9959081c195c9b5a5d606a1b604482015290519081900360640190fd5b6098546001600160a01b038089166000818152609a602090815260408083205481517f00000000000000000000000000000000000000000000000000000000000000008185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e08401855280519082012061190160f01b61010085015261010284019590955261012280840195909552835180840390950185526101429092019092528251920191909120906115ed82868686611ef3565b9050806001600160a01b0316896001600160a01b03161461164b576040805162461bcd60e51b815260206004820152601360248201527211d4950e881a5b9d985b1a59081c195c9b5a5d606a1b604482015290519081900360640190fd5b6001600160a01b0389166000908152609a60205260409020805460010190556116758989896117bc565b505050505050505050565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6001546001600160a01b031681565b6000546001600160a01b03163314611712576040805162461bcd60e51b815260206004820152601660248201527513db9b1e4811dbdd995c9b9bdc8818d85b8818d85b1b60521b604482015290519081900360640190fd5b6001600160a01b038116611764576040805162461bcd60e51b815260206004820152601460248201527311dbdd995c9b9bdc881b5d5cdd081899481cd95d60621b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b03198316179283905560405191811692169082907f76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d90600090a35050565b3390565b6001600160a01b0383166118015760405162461bcd60e51b81526004018080602001828103825260248152602001806125a06024913960400191505060405180910390fd5b6001600160a01b0382166118465760405162461bcd60e51b81526004018080602001828103825260228152602001806124546022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166118ed5760405162461bcd60e51b815260040180806020018281038252602581526020018061257b6025913960400191505060405180910390fd5b6001600160a01b0382166119325760405162461bcd60e51b815260040180806020018281038252602381526020018061240f6023913960400191505060405180910390fd5b61193d838383610c37565b61197a81604051806060016040528060268152602001612476602691396001600160a01b0386166000908152603460205260409020549190611a05565b6001600160a01b0380851660009081526034602052604080822093909355908416815220546119a99082611ae5565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611a945760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611a59578181015183820152602001611a41565b50505050905090810190601f168015611a865780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038116600081815260996020526040808220805460ff19169055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a250565b600082820183811015611b3f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216611ba1576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b611bad60008383610c37565b603654611bba9082611ae5565b6036556001600160a01b038216600090815260346020526040902054611be09082611ae5565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216611c7d5760405162461bcd60e51b815260040180806020018281038252602181526020018061255a6021913960400191505060405180910390fd5b611c8982600083610c37565b611cc681604051806060016040528060228152602001612432602291396001600160a01b0385166000908152603460205260409020549190611a05565b6001600160a01b038316600090815260346020526040902055603654611cec9082612071565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b038116600081815260996020526040808220805460ff19166001179055517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69190a250565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611db0306120ce565b15905090565b611dfe6040518060400160405280600b81526020016a23b930b834102a37b5b2b760a91b8152506040518060400160405280600381526020016211d49560ea1b8152506120d4565b611e07826121a0565b611e118282611b46565b611e1a82611d34565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e856121c2565b6040805160208082019690965280820194909452606084019290925260808301523060a08301527f000000000000000000000000000000000000000000000000000000000000000060c0808401919091528151808403909101815260e0909201905280519101206098555050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611f545760405162461bcd60e51b815260040180806020018281038252602281526020018061249c6022913960400191505060405180910390fd5b8360ff16601b1480611f6957508360ff16601c145b611fa45760405162461bcd60e51b81526004018080602001828103825260228152602001806124ec6022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612068576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b6000828211156120c8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b3b151590565b600154600160a81b900460ff16806120ef57506120ef611da5565b806121045750600154600160a01b900460ff16155b61213f5760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612176576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b61217e6121c6565b612188838361227e565b8015610c37576001805460ff60a81b19169055505050565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b4690565b600154600160a81b900460ff16806121e157506121e1611da5565b806121f65750600154600160a01b900460ff16155b6122315760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612268576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b8015610955576001805460ff60a81b1916905550565b600154600160a81b900460ff16806122995750612299611da5565b806122ae5750600154600160a01b900460ff16155b6122e95760405162461bcd60e51b815260040180806020018281038252602e8152602001806124be602e913960400191505060405180910390fd5b600154600160a81b900460ff16158015612320576001805460ff60a01b1960ff60a81b19909116600160a81b1716600160a01b1790555b825161233390603790602086019061236d565b50815161234790603890602085019061236d565b506039805460ff191660121790558015610c37576001805460ff60a81b19169055505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826123a357600085556123e9565b82601f106123bc57805160ff19168380011785556123e9565b828001600101855582156123e9579182015b828111156123e95782518255916020019190600101906123ce565b506123f59291506123f9565b5090565b5b808211156123f557600081556001016123fa56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545434453413a20696e76616c6964207369676e6174757265202773272076616c7565496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ff9ed43c1b257716d58111b6358b62039b7d7359bc9f0f142332535a4370cafe64736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken","networkInteractionId":1,"nonce":546,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"217400000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x00f6557a96a5ae41f6adec963655d4755afe277f26c9fe32135cde7765a81f65"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphToken#GraphToken","hash":"0x00f6557a96a5ae41f6adec963655d4755afe277f26c9fe32135cde7765a81f65","networkInteractionId":1,"receipt":{"blockHash":"0x088309bc6623f9e99cfd3785c785e61b0232ea8b254ece414d75a207ef8ce060","blockNumber":82177368,"contractAddress":"0x21Ee267Efe20A7E846964D3f9E28F7e81d72547e","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken","result":{"address":"0x21Ee267Efe20A7E846964D3f9E28F7e81d72547e","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphTokenGateway#GraphTokenGateway","constructorArgs":[],"contractName":"GraphTokenGateway","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"GraphTokenGateway#GraphTokenGateway","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphTokenGateway","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e05161010051610120516101405161222b6101696000398061112f5250806111065250806110dd528061150a5250806110b452508061108b525080611062525080611039525061222b6000f3fe6080604052600436106101405760003560e01c806392eefe9b116100b6578063c4d66de81161006f578063c4d66de814610355578063d2ce7d6514610375578063d685c0b214610388578063d6866ea5146103a8578063f14a4bd5146103bd578063f77c4791146103d257610140565b806392eefe9b146102a05780639ce7abe5146102c0578063a0c76a96146102e0578063a2594d8214610300578063a7e28d4814610320578063c4c0087c1461034057610140565b80634adc698a116101085780634adc698a146101e55780635c975abb146101fa57806369bc8cd41461021c5780636cda37981461023c5780637b3a3c8b1461025e57806391b4ded91461028b57610140565b80630252fec11461014557806316c38b3c1461016757806324a3d622146101875780632e567b36146101b257806348bde20c146101c5575b600080fd5b34801561015157600080fd5b50610165610160366004611b43565b6103e7565b005b34801561017357600080fd5b50610165610182366004611da9565b610474565b34801561019357600080fd5b5061019c61056c565b6040516101a99190611e67565b60405180910390f35b6101656101c0366004611bb4565b61057b565b3480156101d157600080fd5b506101656101e0366004611b43565b6107b3565b3480156101f157600080fd5b5061019c61081f565b34801561020657600080fd5b5061020f61082e565b6040516101a99190611f43565b34801561022857600080fd5b50610165610237366004611b43565b61083c565b34801561024857600080fd5b506102516108b5565b6040516101a991906121a9565b34801561026a57600080fd5b5061027e610279366004611cb4565b6108bb565b6040516101a99190611f4e565b34801561029757600080fd5b506102516108d7565b3480156102ac57600080fd5b506101656102bb366004611b43565b6108dd565b3480156102cc57600080fd5b506101656102db366004611dc9565b6108ee565b3480156102ec57600080fd5b5061027e6102fb366004611c37565b610a44565b34801561030c57600080fd5b5061016561031b366004611b43565b610ac4565b34801561032c57600080fd5b5061019c61033b366004611b43565b610bdf565b34801561034c57600080fd5b5061019c610c0f565b34801561036157600080fd5b50610165610370366004611b43565b610c1e565b61027e610383366004611d25565b610d44565b34801561039457600080fd5b506101656103a3366004611b43565b610fbb565b3480156103b457600080fd5b50610165611034565b3480156103c957600080fd5b5061019c611155565b3480156103de57600080fd5b5061019c611164565b6103ef611173565b6001600160a01b03811661041e5760405162461bcd60e51b815260040161041590612034565b60405180910390fd5b607780546001600160a01b0319166001600160a01b0383161790556040517f43a303848c82a28f94def3043839eaebd654c19fdada874a74fb94d8bf7d343890610469908390611e67565b60405180910390a150565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156104b657600080fd5b505afa1580156104ca573d6000803e3d6000fd5b505050506040513d60208110156104e057600080fd5b50516001600160a01b031633148061050257506003546001600160a01b031633145b610553576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c7920476f7665726e6f72206f7220477561726469616e00000000000000604482015290519081900360640190fd5b806105605761056061123d565b610569816112b5565b50565b6003546001600160a01b031681565b600260435414156105d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026043556105e0611340565b6076546105f5906001600160a01b0316611391565b6001600160a01b0316336001600160a01b0316146106255760405162461bcd60e51b815260040161041590612172565b6075546001600160a01b038781169116146106525760405162461bcd60e51b81526004016104159061214b565b34156106705760405162461bcd60e51b815260040161041590611fdd565b607554610685906001600160a01b0316610bdf565b6001600160a01b0316638c2a993e85856040518363ffffffff1660e01b81526004016106b2929190611ee2565b600060405180830381600087803b1580156106cc57600080fd5b505af11580156106e0573d6000803e3d6000fd5b505082159150610751905057604051635260769b60e11b81526001600160a01b0385169063a4c0ed369061071e908890879087908790600401611efb565b600060405180830381600087803b15801561073857600080fd5b505af115801561074c573d6000803e3d6000fd5b505050505b836001600160a01b0316856001600160a01b0316876001600160a01b03167fc7f2e9c55c40a50fbc217dfc70cd39a222940dfa62145aa0ca49eb9535d4fcb28660405161079e91906121a9565b60405180910390a45050600160435550505050565b6107bb611173565b6001600160a01b038116610816576040805162461bcd60e51b815260206004820152601960248201527f5061757365477561726469616e206d7573742062652073657400000000000000604482015290519081900360640190fd5b610569816113aa565b6077546001600160a01b031681565b600054610100900460ff1690565b610844611173565b6001600160a01b03811661086a5760405162461bcd60e51b81526004016104159061200c565b607580546001600160a01b0319166001600160a01b0383161790556040517f0b7cf729ac6c387cab57a28d257c6ecac863c24b086353121057083c7bfc79f990610469908390611e67565b60015481565b60606108cd8686866000808888610d44565b9695505050505050565b60025481565b6108e56113fc565b6105698161145b565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561092a57600080fd5b505af115801561093e573d6000803e3d6000fd5b505050506040513d602081101561095457600080fd5b50516001600160a01b031633146109b2576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610a2657600080fd5b505af1158015610a3a573d6000803e3d6000fd5b5050505050505050565b6060632e567b3660e01b86868686600087604051602001610a66929190611f61565b60408051601f1981840301815290829052610a879594939291602401611e7b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905095945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b0057600080fd5b505af1158015610b14573d6000803e3d6000fd5b505050506040513d6020811015610b2a57600080fd5b50516001600160a01b03163314610b88576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050505050565b6075546000906001600160a01b03838116911614610bff57506000610c0a565b610c07611503565b90505b919050565b6076546001600160a01b031681565b610c26611533565b6001600160a01b0316336001600160a01b031614610c81576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b604254610100900460ff1680610c9a5750610c9a611558565b80610ca8575060425460ff16155b610ce35760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015610d0e576042805460ff1961ff0019909116610100171660011790555b610d17826108e5565b6000805461ff001916610100179055610d2e611569565b8015610d40576042805461ff00191690555b5050565b606060026043541415610d9e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002604355610dab611340565b6075546001600160a01b03898116911614610dd85760405162461bcd60e51b81526004016104159061214b565b85610df55760405162461bcd60e51b815260040161041590611fb0565b3415610e135760405162461bcd60e51b815260040161041590611fdd565b6001600160a01b038716610e395760405162461bcd60e51b81526004016104159061205f565b610e41611a76565b610e4b8484611612565b602083018190526001600160a01b0390911682525115610e7d5760405162461bcd60e51b8152600401610415906120bc565b607554610e92906001600160a01b0316610bdf565b81516040516374f4f54760e01b81526001600160a01b0392909216916374f4f54791610ec2918b90600401611ee2565b600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506000610f3060008360000151607660009054906101000a90046001600160a01b0316610f2b8e87600001518f8f8a60200151610a44565b61168f565b905080896001600160a01b031683600001516001600160a01b03167f3073a74ecb728d10be779fe19a74a1428e20468f5b4d167bf9c73d9067847d738d60008d604051610f7f93929190611ec1565b60405180910390a480604051602001610f9891906121a9565b604051602081830303815290604052925050506001604355979650505050505050565b610fc3611173565b6001600160a01b038116610fe95760405162461bcd60e51b81526004016104159061208c565b607680546001600160a01b0319166001600160a01b0383161790556040517f60d5265d09ed32300af9a69188333d24b405b6f4196f623f3e2b78321181a61590610469908390611e67565b61105d7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110867f000000000000000000000000000000000000000000000000000000000000000061182f565b6110af7f000000000000000000000000000000000000000000000000000000000000000061182f565b6110d87f000000000000000000000000000000000000000000000000000000000000000061182f565b6111017f000000000000000000000000000000000000000000000000000000000000000061182f565b61112a7f000000000000000000000000000000000000000000000000000000000000000061182f565b6111537f000000000000000000000000000000000000000000000000000000000000000061182f565b565b6075546001600160a01b031681565b6004546001600160a01b031681565b6004805460408051634fc07d7560e01b815290516001600160a01b0390921692634fc07d75928282019260209290829003018186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d60208110156111df57600080fd5b50516001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b6077546001600160a01b03166112655760405162461bcd60e51b815260040161041590611f85565b6076546001600160a01b031661128d5760405162461bcd60e51b8152600401610415906120f3565b6075546001600160a01b03166111535760405162461bcd60e51b815260040161041590612123565b600060019054906101000a900460ff16151581151514156112d557610569565b6000805461ff0019166101008315158102919091179182905560ff910416156112fd57426002555b6000546040805161010090920460ff1615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5916020908290030190a150565b600054610100900460ff1615611153576040805162461bcd60e51b81526020600482015260116024820152705061757365642028636f6e74726163742960781b604482015290519081900360640190fd5b7311110000000000000000000000000000000011110190565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90600090a35050565b6004546001600160a01b03163314611153576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166114af576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b600061152e7f0000000000000000000000000000000000000000000000000000000000000000611930565b905090565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000611563306119ca565b15905090565b604254610100900460ff16806115825750611582611558565b80611590575060425460ff16155b6115cb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff161580156115f6576042805460ff1961ff0019909116610100171660011790555b6115fe6119d0565b8015610569576042805461ff001916905550565b607754600090606090829082906001600160a01b03163314156116455761163b85870187611b66565b9092509050611682565b33915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b90925090505b9250929050565b60008060646001600160a01b031663928c169a8786866040518463ffffffff1660e01b815260040180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156117005781810151838201526020016116e8565b50505050905090810190601f16801561172d5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818588803b15801561174c57600080fd5b505af1158015611760573d6000803e3d6000fd5b50505050506040513d602081101561177757600080fd5b5051604080516020808252865182820152865193945084936001600160a01b03808a1694908b16937f2b986d32a0536b7e19baa48ab949fec7b903b7fad7730820b20632d100cc3a68938a93919283929083019185019080838360005b838110156117ec5781810151838201526020016117d4565b50505050905090810190601f1680156118195780820380516001836020036101000a031916815260200191505b509250505060405180910390a495945050505050565b6004805460408051637bb20d2f60e11b8152928301849052516000926001600160a01b039092169163f7641a5e916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b50516000838152600560205260409020549091506001600160a01b03808316911614610d405760008281526005602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000818152600560205260408120546001600160a01b031680610c07576004805460408051637bb20d2f60e11b8152928301869052516001600160a01b039091169163f7641a5e916024808301926020929190829003018186803b15801561199757600080fd5b505afa1580156119ab573d6000803e3d6000fd5b505050506040513d60208110156119c157600080fd5b50519392505050565b3b151590565b604254610100900460ff16806119e957506119e9611558565b806119f7575060425460ff16155b611a325760405162461bcd60e51b815260040180806020018281038252602e8152602001806121c8602e913960400191505060405180910390fd5b604254610100900460ff16158015611a5d576042805460ff1961ff0019909116610100171660011790555b60016043558015610569576042805461ff001916905550565b60408051808201909152600081526060602082015290565b60008083601f840112611a9f578182fd5b50813567ffffffffffffffff811115611ab6578182fd5b60208301915083602082850101111561168857600080fd5b600082601f830112611ade578081fd5b813567ffffffffffffffff80821115611af357fe5b604051601f8301601f191681016020018281118282101715611b1157fe5b604052828152848301602001861015611b28578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215611b54578081fd5b8135611b5f816121b2565b9392505050565b60008060408385031215611b78578081fd5b8235611b83816121b2565b9150602083013567ffffffffffffffff811115611b9e578182fd5b611baa85828601611ace565b9150509250929050565b60008060008060008060a08789031215611bcc578182fd5b8635611bd7816121b2565b95506020870135611be7816121b2565b94506040870135611bf7816121b2565b935060608701359250608087013567ffffffffffffffff811115611c19578283fd5b611c2589828a01611a8e565b979a9699509497509295939492505050565b600080600080600060a08688031215611c4e578081fd5b8535611c59816121b2565b94506020860135611c69816121b2565b93506040860135611c79816121b2565b925060608601359150608086013567ffffffffffffffff811115611c9b578182fd5b611ca788828901611ace565b9150509295509295909350565b600080600080600060808688031215611ccb578081fd5b8535611cd6816121b2565b94506020860135611ce6816121b2565b935060408601359250606086013567ffffffffffffffff811115611d08578182fd5b611d1488828901611a8e565b969995985093965092949392505050565b600080600080600080600060c0888a031215611d3f578081fd5b8735611d4a816121b2565b96506020880135611d5a816121b2565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115611d8a578182fd5b611d968a828b01611a8e565b989b979a50959850939692959293505050565b600060208284031215611dba578081fd5b81358015158114611b5f578182fd5b600080600060408486031215611ddd578283fd5b8335611de8816121b2565b9250602084013567ffffffffffffffff811115611e03578283fd5b611e0f86828701611a8e565b9497909650939450505050565b60008151808452815b81811015611e4157602081850181015186830182015201611e25565b81811115611e525782602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528581166020830152841660408201526060810183905260a060808201819052600090611eb690830184611e1c565b979650505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0385168152602081018490526060604082018190528101829052600082846080840137818301608090810191909152601f909201601f191601019392505050565b901515815260200190565b600060208252611b5f6020830184611e1c565b600060ff8416825260406020830152611f7d6040830184611e1c565b949350505050565b602080825260119082015270130c97d493d555115497d393d517d4d155607a1b604082015260600190565b6020808252601390820152721253959053125117d6915493d7d05353d55395606a1b604082015260600190565b602080825260159082015274494e56414c49445f4e4f4e5a45524f5f56414c554560581b604082015260600190565b6020808252600e908201526d1253959053125117d30c57d1d49560921b604082015260600190565b60208082526011908201527024a72b20a624a22fa6192fa927aaaa22a960791b604082015260600190565b60208082526013908201527224a72b20a624a22fa222a9aa24a720aa24a7a760691b604082015260600190565b6020808252601690820152751253959053125117d30c57d0d3d5539511549410549560521b604082015260600190565b6020808252601a908201527f43414c4c5f484f4f4b5f444154415f4e4f545f414c4c4f574544000000000000604082015260600190565b602080825260169082015275130c57d0d3d5539511549410549517d393d517d4d15560521b604082015260600190565b6020808252600e908201526d130c57d1d49517d393d517d4d15560921b604082015260600190565b6020808252600d908201526c1513d2d15397d393d517d1d495609a1b604082015260600190565b60208082526018908201527f4f4e4c595f434f554e544552504152545f474154455741590000000000000000604082015260600190565b90815260200190565b6001600160a01b038116811461056957600080fdfe496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c46e838e84462780e008baa7cf28f077541133c7ed1702897fcb4896090a74b664736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphTokenGateway","networkInteractionId":1,"nonce":547,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"210780000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x6aa66e37bdd03eb8836ed26d2a842176829960acf04a874f046cab24afef832e"},"type":"TRANSACTION_SEND"} +{"artifactId":"HorizonProxies#OZProxyDummy_GraphPayments","constructorArgs":[],"contractName":"Dummy","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonProxies#OZProxyDummy_GraphPayments","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","networkInteractionId":1,"nonce":548,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"205960000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x2eb7594c75c7ff384ca16ebc397a76e273105b68085c08a6a2c387d46daca53f"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","hash":"0x2eb7594c75c7ff384ca16ebc397a76e273105b68085c08a6a2c387d46daca53f","networkInteractionId":1,"receipt":{"blockHash":"0xf0aa59865bc193adaf0dedbe871db594d0bcbf26d6d8f11fd4d56ed6b1e2cfe2","blockNumber":82177398,"contractAddress":"0x60eE16fc2C4729343C7B3Ab9B322b2C6CcfbC681","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#OZProxyDummy_GraphPayments","result":{"address":"0x60eE16fc2C4729343C7B3Ab9B322b2C6CcfbC681","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","constructorArgs":[],"contractName":"Dummy","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","networkInteractionId":1,"nonce":549,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"207060000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x9c845a67136d4e880d16a43ed03ef667077148a3b543613c7c4c0db6808ca10b"},"type":"TRANSACTION_SEND"} +{"artifactId":"HorizonStakingExtension#ExponentialRebates","constructorArgs":[],"contractName":"ExponentialRebates","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonStakingExtension#ExponentialRebates","futureType":"LIBRARY_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStakingExtension#ExponentialRebates","networkInteraction":{"data":"0x610c2d610039600b82828239805160001a607314602c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c806349484d811461003a575b600080fd5b61004d610048366004610a66565b61005f565b60405190815260200160405180910390f35b6000806100728660030b8660030b61011c565b9050806000036100855787915050610112565b87600003610097576000915050610112565b60006100a98560030b8560030b61011c565b905060006100b8828a8c61013c565b9050600f6100c582610153565b13156100d657899350505050610112565b60006100ff6001607f1b6100fa866100f56100f087610ae2565b610169565b610882565b61089d565b905061010b818c6108d4565b9450505050505b9695505050505050565b600061013561012f846001607f1b610920565b83610988565b9392505050565b600061014b61012f8585610920565b949350505050565b60006101636001607f1b83610b14565b92915050565b60006101796101ff607c1b610ae2565b82121561018857506000919050565b8160000361019b57506001607f1b919050565b60008213156101c55760405162461bcd60e51b81526004016101bc90610b42565b60405180910390fd5b6000806101d66001607c1b85610b69565b91508190506001607f1b6101ea8280610b7d565b6101f49190610b14565b9050610208816710e1b3be415a0000610b7d565b6102129084610bad565b92506001607f1b6102238383610b7d565b61022d9190610b14565b9050610241816705a0913f6b1e0000610b7d565b61024b9084610bad565b92506001607f1b61025c8383610b7d565b6102669190610b14565b905061027a81670168244fdac78000610b7d565b6102849084610bad565b92506001607f1b6102958383610b7d565b61029f9190610b14565b90506102b281664807432bc18000610b7d565b6102bc9084610bad565b92506001607f1b6102cd8383610b7d565b6102d79190610b14565b90506102ea81660c0135dca04000610b7d565b6102f49084610bad565b92506001607f1b6103058383610b7d565b61030f9190610b14565b9050610322816601b707b1cdc000610b7d565b61032c9084610bad565b92506001607f1b61033d8383610b7d565b6103479190610b14565b9050610359816536e0f639b800610b7d565b6103639084610bad565b92506001607f1b6103748383610b7d565b61037e9190610b14565b905061039081650618fee9f800610b7d565b61039a9084610bad565b92506001607f1b6103ab8383610b7d565b6103b59190610b14565b90506103c681649c197dcc00610b7d565b6103d09084610bad565b92506001607f1b6103e18383610b7d565b6103eb9190610b14565b90506103fc81640e30dce400610b7d565b6104069084610bad565b92506001607f1b6104178383610b7d565b6104219190610b14565b90506104328164012ebd1300610b7d565b61043c9084610bad565b92506001607f1b61044d8383610b7d565b6104579190610b14565b9050610467816317499f00610b7d565b6104719084610bad565b92506001607f1b6104828383610b7d565b61048c9190610b14565b905061049c816301a9d480610b7d565b6104a69084610bad565b92506001607f1b6104b78383610b7d565b6104c19190610b14565b90506104d081621c6380610b7d565b6104da9084610bad565b92506001607f1b6104eb8383610b7d565b6104f59190610b14565b9050610504816201c638610b7d565b61050e9084610bad565b92506001607f1b61051f8383610b7d565b6105299190610b14565b905061053781611ab8610b7d565b6105419084610bad565b92506001607f1b6105528383610b7d565b61055c9190610b14565b905061056a8161017c610b7d565b6105749084610bad565b92506001607f1b6105858383610b7d565b61058f9190610b14565b905061059c816014610b7d565b6105a69084610bad565b92506001607f1b6105b78383610b7d565b6105c19190610b14565b90506105ce816001610b7d565b6105d89084610bad565b92506001607f1b826105f26721c3677c82b4000086610b14565b6105fc9190610bad565b6106069190610bad565b925061061184610ae2565b9350600160841b841615610657577243cbaf42a000812488fc5c220ad7b97bf6e99e61064a6cf1aaddd7742e56d32fb9f9974485610b7d565b6106549190610b14565b92505b600160831b84161561069c577105d27a9f51c31b7c2f8038212a057477999161068f6e0afe10820813d65dfe6a33c07f738f85610b7d565b6106999190610b14565b92505b600160821b8416156106e157701b4c902e273a58678d6d3bfdb93db96d026106d46f02582ab704279e8efd15e0265855c47a85610b7d565b6106de9190610b14565b92505b600160811b841615610726577003b1cc971a9bb5b9867477440d6d1577506107196f1152aaa3bf81cb9fdb76eae12d02957185610b7d565b6107239190610b14565b92505b600160801b84161561076b5770015bf0a8b1457695355fb8ac404e7a79e361075e6f2f16ac6c59de6f8d5d6f63c1482a7c8685610b7d565b6107689190610b14565b92505b6001607f1b8416156107af576fd3094c70f034de4b96ff7d5b6f99fcd86107a26f4da2cbf1be5827f9eb3ad1aa9866ebb385610b7d565b6107ac9190610b14565b92505b6001607e1b8416156107f3576fa45af1e1f40c333b3de1db4dd55f29a76107e66f63afbe7ab2082ba1a0ae5e4eb1b479dc85610b7d565b6107f09190610b14565b92505b6001607d1b841615610837576f910b022db7ae67ce76b441c27035c6a161082a6f70f5a893b608861e1f58934f97aea57d85610b7d565b6108349190610b14565b92505b6001607c1b84161561087b576f88415abbe9a76bead8d00cf112e4d4a861086e6f783eafef1c0a8f3978c7f81824d62ebf85610b7d565b6108789190610b14565b92505b5050919050565b60006001607f1b6108938484610920565b6101359190610b14565b6000600160ff1b82036108c25760405162461bcd60e51b81526004016101bc90610b42565b610135836108cf84610ae2565b6109f2565b6000808212156108f65760405162461bcd60e51b81526004016101bc90610b42565b60006109028484610920565b905060008113610916576000915050610163565b607f1c9392505050565b600082158061092d575081155b1561093a57506000610163565b508181028183828161094e5761094e610afe565b0514158061096b57508282828161096757610967610afe565b0514155b156101635760405162461bcd60e51b81526004016101bc90610bd5565b6000816000036109aa5760405162461bcd60e51b81526004016101bc90610bd5565b600160ff1b831480156109be575081600019145b156109db5760405162461bcd60e51b81526004016101bc90610bd5565b8183816109ea576109ea610afe565b059392505050565b818101600083128015610a055750600082125b8015610a1057508281135b8061096b5750600083138015610a265750600082135b801561096b5750828112156101635760405162461bcd60e51b81526004016101bc90610bd5565b803563ffffffff81168114610a6157600080fd5b919050565b60008060008060008060c08789031215610a7f57600080fd5b8635955060208701359450610a9660408801610a4d565b9350610aa460608801610a4d565b9250610ab260808801610a4d565b9150610ac060a08801610a4d565b90509295509295509295565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201610af757610af7610acc565b5060000390565b634e487b7160e01b600052601260045260246000fd5b600082610b2357610b23610afe565b600160ff1b821460001984141615610b3d57610b3d610acc565b500590565b6020808252600d908201526c6f75742d6f662d626f756e647360981b604082015260600190565b600082610b7857610b78610afe565b500790565b80820260008212600160ff1b84141615610b9957610b99610acc565b818105831482151761016357610163610acc565b8082018281126000831280158216821582161715610bcd57610bcd610acc565b505092915050565b6020808252600890820152676f766572666c6f7760c01b60408201526060019056fea26469706673582212201cac81319f1bc19d15bc3a02519b03e3559a9cf147525a96caa8cb800f74da2864736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStakingExtension#ExponentialRebates","networkInteractionId":1,"nonce":550,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"215140000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xbb35e8b121d2a979dff148e7e9bad2860880ca8532c9eeea02b3dc7b98c9152c"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonStakingExtension#ExponentialRebates","hash":"0xbb35e8b121d2a979dff148e7e9bad2860880ca8532c9eeea02b3dc7b98c9152c","networkInteractionId":1,"receipt":{"blockHash":"0x55cb8a0a9b4deecfb10db48511b1c625831831e917eb5dc2aca575e508baa5ae","blockNumber":82177430,"contractAddress":"0x5Ab8e4eDb2d068C9c1ab9c96bfb3abCAb96e1534","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStakingExtension#ExponentialRebates","result":{"address":"0x5Ab8e4eDb2d068C9c1ab9c96bfb3abCAb96e1534","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"RewardsManager#RewardsManager","constructorArgs":[],"contractName":"RewardsManager","dependencies":[],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"RewardsManager#RewardsManager","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager","networkInteraction":{"data":"0x6101606040527fe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f6080527fc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f6706360a0527f966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c5318076160c0527f1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d16703460e0527f45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247610100527fd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0610120527f39605a6c26a173774ca666c67ef70cf491880e5d3d6d0ca66ec0a31034f15ea36101405234801561011057600080fd5b5060805160a05160c05160e051610100516101205161014051611eb861017360003980610fe1525080610fb8525080610f8f528061194f525080610f6652806116d2525080610f3d525080610f14525080610eeb52806115165250611eb86000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806392eefe9b1161010f578063c8a5f81e116100a2578063e284f84811610071578063e284f848146103cb578063e820e284146103d3578063eeac3e0e146103f3578063f77c479114610406576101e5565b8063c8a5f81e14610395578063d6866ea5146103a8578063db750926146103b0578063e242cf1e146103c3576101e5565b8063a8cc0ee2116100de578063a8cc0ee21461036a578063b951acd714610372578063c4d66de81461037a578063c7d1117d1461038d576101e5565b806392eefe9b1461031e57806393a90a1e146103315780639ce7abe514610344578063a2594d8214610357576101e5565b806326058249116101875780636c080f18116101565780636c080f18146102da578063702a280e146102e257806379ee54f7146103035780639006ce8b14610316576101e5565b806326058249146102895780634986594f146102915780634bbfc1c5146102b45780635c6cbd59146102c7576101e5565b80631324a506116101c35780631324a5061461023057806316a84ab2146102435780631d1c2fec146102635780631debaded14610276576101e5565b806305bb8c6b146101ea5780630903c094146102085780631156bdc11461021d575b600080fd5b6101f261040e565b6040516101ff9190611c75565b60405180910390f35b61021b610216366004611a54565b61041d565b005b61021b61022b366004611b75565b610479565b61021b61023e366004611b8d565b61048d565b610256610251366004611b75565b6104ce565b6040516101ff9190611cad565b610256610271366004611b75565b6104e0565b61021b610284366004611ad4565b610519565b6101f26105b8565b6102a461029f366004611b75565b6105c7565b6040516101ff9493929190611e23565b61021b6102c2366004611b75565b6105ee565b6102566102d5366004611b75565b6106ea565b6102566107db565b6102f56102f0366004611b75565b6107e1565b6040516101ff929190611e15565b610256610311366004611a54565b610955565b610256610b3d565b61021b61032c366004611a54565b610b43565b61021b61033f366004611a54565b610b54565b61021b610352366004611bbc565b610bae565b61021b610365366004611a54565b610d04565b610256610e1f565b610256610e3b565b61021b610388366004611a54565b610e41565b610256610ead565b6102566103a3366004611c54565b610ec5565b61021b610ee6565b6102566103be366004611a54565b611007565b610256611232565b610256611238565b6103e66103e1366004611b75565b611347565b6040516101ff9190611ca2565b610256610401366004611b75565b61135b565b6101f261138d565b600f546001600160a01b031681565b61042561139c565b600f80546001600160a01b0319166001600160a01b0383161790556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611cb6565b60405180910390a150565b61048161139c565b61048a81611470565b50565b600f546001600160a01b031633146104c05760405162461bcd60e51b81526004016104b790611ced565b60405180910390fd5b6104ca82826114ac565b5050565b60116020526000908152604090205481565b60006104ea610ead565b506000828152601060205260409020610502836106ea565b808255600d5460029092019190915590505b919050565b600f546001600160a01b031633146105435760405162461bcd60e51b81526004016104b790611ced565b8281146105625760405162461bcd60e51b81526004016104b790611dcc565b60005b838110156105b1576105a985858381811061057c57fe5b9050602002013584848481811061058f57fe5b90506020020160208101906105a49190611b3d565b6114ac565b600101610565565b5050505050565b6015546001600160a01b031681565b60106020526000908152604090208054600182015460028301546003909301549192909184565b600f546001600160a01b031633148061069b575060008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b15801561064e57600080fd5b505afa158015610662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106869190611a70565b6001600160a01b0316336001600160a01b0316145b6106b75760405162461bcd60e51b81526004016104b790611ded565b60128190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d3c565b60008181526010602052604081208161070161150f565b6001600160a01b03166346e855da856040518263ffffffff1660e01b815260040161072c9190611cad565b60206040518083038186803b15801561074457600080fd5b505afa158015610758573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077c9190611c3c565b905060006012548210156107915760006107c3565b6107c3670de0b6b3a76400006107bd846107b787600201546107b1610e1f565b9061153a565b90611597565b906115f0565b83549091506107d29082611657565b95945050505050565b60145481565b60008181526010602052604081208190816107fb856106ea565b9050600061080d8284600101546116b1565b905060008060405180604001604052806108256116cb565b6001600160a01b03908116825260155416602090910152905060005b600281101561090457600082826002811061085857fe5b60200201516001600160a01b0316146108fc5781816002811061087757fe5b60200201516001600160a01b031663e2e1e8e98a6040518263ffffffff1660e01b81526004016108a79190611cad565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190611c3c565b830192505b600101610841565b508161091b57600084965096505050505050610950565b6000610933836107bd86670de0b6b3a7640000611597565b60038701549091506109459082611657565b975093955050505050505b915091565b60008060009050600060405180604001604052806109716116cb565b6001600160a01b03908116825260155416602090910152905060005b6002811015610a685760008282600281106109a457fe5b60200201516001600160a01b031614610a60578181600281106109c357fe5b60200201516001600160a01b0316636a3ca383866040518263ffffffff1660e01b81526004016109f39190611c75565b60206040518083038186803b158015610a0b57600080fd5b505afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611b59565b15610a6057818160028110610a5457fe5b60200201519250610a68565b60010161098d565b506001600160a01b038216610a8257600092505050610514565b600080600080856001600160a01b03166355c85269896040518263ffffffff1660e01b8152600401610ab49190611c75565b60a06040518083038186803b158015610acc57600080fd5b505afa158015610ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b049190611a8c565b9450945094509450506000610b18856107e1565b509050610b30610b298585846116f6565b8390611657565b9998505050505050505050565b600e5481565b610b4b61171b565b61048a8161177a565b610b5c61139c565b601580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede90600090a35050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610bea57600080fd5b505af1158015610bfe573d6000803e3d6000fd5b505050506040513d6020811015610c1457600080fd5b50516001600160a01b03163314610c72576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b60405163623faf6160e01b8152602060048201908152602482018490526001600160a01b0386169163623faf619186918691908190604401848480828437600081840152601f19601f8201169050808301925050509350505050600060405180830381600087803b158015610ce657600080fd5b505af1158015610cfa573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d4057600080fd5b505af1158015610d54573d6000803e3d6000fd5b505050506040513d6020811015610d6a57600080fd5b50516001600160a01b03163314610dc8576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015290519081900360640190fd5b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e0357600080fd5b505af1158015610e17573d6000803e3d6000fd5b505050505050565b6000610e35610e2c611238565b600d5490611657565b90505b90565b60125481565b610e49611822565b6001600160a01b0316336001600160a01b031614610ea4576040805162461bcd60e51b815260206004820152601360248201527227b7363c9034b6b83632b6b2b73a30ba34b7b760691b604482015290519081900360640190fd5b61048a81610b4b565b6000610eb7610e1f565b600d81905543600e55905090565b6000610edd670de0b6b3a76400006107bd8486611597565b90505b92915050565b610f0f7f0000000000000000000000000000000000000000000000000000000000000000611847565b610f387f0000000000000000000000000000000000000000000000000000000000000000611847565b610f617f0000000000000000000000000000000000000000000000000000000000000000611847565b610f8a7f0000000000000000000000000000000000000000000000000000000000000000611847565b610fb37f0000000000000000000000000000000000000000000000000000000000000000611847565b610fdc7f0000000000000000000000000000000000000000000000000000000000000000611847565b6110057f0000000000000000000000000000000000000000000000000000000000000000611847565b565b6000336110126116cb565b6001600160a01b0316816001600160a01b0316148061103e57506015546001600160a01b038281169116145b61105a5760405162461bcd60e51b81526004016104b790611d95565b6000806000806000856001600160a01b03166355c85269896040518263ffffffff1660e01b815260040161108e9190611c75565b60a06040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190611a8c565b9450945094509450945060006110f38561135b565b90506110fe85611347565b1561115357886001600160a01b0316866001600160a01b03167f9b1323a10f3955b1c9c054ffbda78edfdf49998aaf37f61d9f84776b59ac804360405160405180910390a36000975050505050505050610514565b600061116a6111638686856116f6565b8490611657565b905080156111da5761117a611948565b6001600160a01b03166340c10f1989836040518363ffffffff1660e01b81526004016111a7929190611c89565b600060405180830381600087803b1580156111c157600080fd5b505af11580156111d5573d6000803e3d6000fd5b505050505b896001600160a01b0316876001600160a01b03167fbf5617ec135b48259c44e1ae312a03606f36e174082ef2e87042b86ceebace648360405161121d9190611cad565b60405180910390a39998505050505050505050565b600d5481565b600080611250600e544361153a90919063ffffffff16565b905080611261576000915050610e38565b601454611272576000915050610e38565b600061127c611948565b90506000816001600160a01b03166370a0823161129761150f565b6040518263ffffffff1660e01b81526004016112b39190611c75565b60206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113039190611c3c565b9050806113165760009350505050610e38565b6014546000906113269085611597565b905061133e826107bd83670de0b6b3a7640000611597565b94505050505090565b600090815260116020526040902054151590565b60008181526010602052604081208180611374856107e1565b6003850182905560019094019390935550909392505050565b6000546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316634fc07d756040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e857600080fd5b505afa1580156113fc573d6000803e3d6000fd5b505050506040513d602081101561141257600080fd5b50516001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601860248201527f4f6e6c7920436f6e74726f6c6c657220676f7665726e6f720000000000000000604482015290519081900360640190fd5b611478610ead565b5060148190556040517f96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c9061046e90611d6b565b6000816114ba5760006114bc565b435b600084815260116020526040908190208290555190915083907fe016102b339c3889f4967b491f3381f2c352c8fe3d4f880007807d45b124065a90611502908490611cad565b60405180910390a2505050565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600082821115611591576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826115a657506000610ee0565b828202828482816115b357fe5b0414610edd5760405162461bcd60e51b8152600401808060200182810382526021815260200180611e626021913960400191505060405180910390fd5b6000808211611646576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161164f57fe5b049392505050565b600082820183811015610edd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008183116116c1576000610edd565b610edd838361153a565b6000610e357f000000000000000000000000000000000000000000000000000000000000000061196f565b600080611703838561153a565b90506107d2670de0b6b3a76400006107bd8388611597565b6000546001600160a01b03163314611005576040805162461bcd60e51b815260206004820152601960248201527f43616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015290519081900360640190fd5b6001600160a01b0381166117ce576040805162461bcd60e51b815260206004820152601660248201527510dbdb9d1c9bdb1b195c881b5d5cdd081899481cd95d60521b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709181900360200190a150565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000805460408051637bb20d2f60e11b81526004810185905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b15801561189457600080fd5b505afa1580156118a8573d6000803e3d6000fd5b505050506040513d60208110156118be57600080fd5b50516000838152600160205260409020549091506001600160a01b038083169116146104ca5760008281526001602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251908152915184927fd0e7a942b1fc38c411c4f53d153ba14fd24542a6a35ebacd9b6afca1a154e20692908290030190a25050565b6000610e357f00000000000000000000000000000000000000000000000000000000000000005b6000818152600160205260408120546001600160a01b031680610ee05760005460408051637bb20d2f60e11b81526004810186905290516001600160a01b039092169163f7641a5e91602480820192602092909190829003018186803b1580156119d857600080fd5b505afa1580156119ec573d6000803e3d6000fd5b505050506040513d6020811015611a0257600080fd5b50519392505050565b60008083601f840112611a1c578182fd5b50813567ffffffffffffffff811115611a33578182fd5b6020830191508360208083028501011115611a4d57600080fd5b9250929050565b600060208284031215611a65578081fd5b8135610edd81611e3e565b600060208284031215611a81578081fd5b8151610edd81611e3e565b600080600080600060a08688031215611aa3578081fd5b8551611aae81611e3e565b602087015160408801516060890151608090990151929a91995097965090945092505050565b60008060008060408587031215611ae9578384fd5b843567ffffffffffffffff80821115611b00578586fd5b611b0c88838901611a0b565b90965094506020870135915080821115611b24578384fd5b50611b3187828801611a0b565b95989497509550505050565b600060208284031215611b4e578081fd5b8135610edd81611e53565b600060208284031215611b6a578081fd5b8151610edd81611e53565b600060208284031215611b86578081fd5b5035919050565b60008060408385031215611b9f578182fd5b823591506020830135611bb181611e53565b809150509250929050565b600080600060408486031215611bd0578283fd5b8335611bdb81611e3e565b9250602084013567ffffffffffffffff80821115611bf7578384fd5b818601915086601f830112611c0a578384fd5b813581811115611c18578485fd5b876020828501011115611c29578485fd5b6020830194508093505050509250925092565b600060208284031215611c4d578081fd5b5051919050565b60008060408385031215611c66578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b6020808252601a908201527f7375626772617068417661696c6162696c6974794f7261636c65000000000000604082015260600190565b6020808252602f908201527f43616c6c6572206d75737420626520746865207375626772617068206176616960408201526e6c6162696c697479206f7261636c6560881b606082015260800190565b6020808252601590820152741b5a5b9a5b5d5b54dd5899dc985c1a14da59db985b605a1b604082015260600190565b60208082526010908201526f69737375616e6365506572426c6f636b60801b604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206120726577617264732069737375657200604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b918252602082015260400190565b93845260208401929092526040830152606082015260800190565b6001600160a01b038116811461048a57600080fd5b801515811461048a57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122065ddb3a88a231d6b2a7b9fa381d5dcb967f78c91305d391f4715ef7d2c04ab4764736f6c63430007060033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager","networkInteractionId":1,"nonce":551,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"221200000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xdb2ae2bd7ac518f58197eb2cb834add2982f44ec501652d7f91d14d2eb81b8c1"},"type":"TRANSACTION_SEND"} +{"futureId":"RewardsManager#RewardsManager","hash":"0xdb2ae2bd7ac518f58197eb2cb834add2982f44ec501652d7f91d14d2eb81b8c1","networkInteractionId":1,"receipt":{"blockHash":"0xac102f4a39375b63fbd580c45c6f05f8b6e2dcdbf1a6da09221688f7ba352b1a","blockNumber":82177446,"contractAddress":"0xE7ed8F3e83a10a74CBfaDdC7596CBb79c4eccA17","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager","result":{"address":"0xE7ed8F3e83a10a74CBfaDdC7596CBb79c4eccA17","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"Controller#Controller","hash":"0x22f6e912acc9d7888fadcb3b37c4989b24c418547984408f34feccaad11edaab","networkInteractionId":1,"receipt":{"blockHash":"0xa996896b33b1bca181707ccde90c8a26fbc03834c56ac7cf50750e55d2df256f","blockNumber":82177294,"contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000000000000000000000000000000000000000000001","logIndex":0,"topics":["0x8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Controller#Controller","result":{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphTokenGateway#GraphTokenGateway","hash":"0x6aa66e37bdd03eb8836ed26d2a842176829960acf04a874f046cab24afef832e","networkInteractionId":1,"receipt":{"blockHash":"0x93aaf290de7cae94b0fc57e22f469dffbd123951fed875ea89980819f2ed1164","blockNumber":82177383,"contractAddress":"0x2f3f6fbAD807800da2d1ABC9c949c45Bc1C81541","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphTokenGateway","result":{"address":"0x2f3f6fbAD807800da2d1ABC9c949c45Bc1C81541","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","hash":"0x9c845a67136d4e880d16a43ed03ef667077148a3b543613c7c4c0db6808ca10b","networkInteractionId":1,"receipt":{"blockHash":"0xa8e51d3cec86d0a8e35e739cafa1b01be1f42ad1766275f6ccba608ab1bbfde5","blockNumber":82177414,"contractAddress":"0xF39FD65373870fcb5868F7458d8d84485E5Bf890","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#OZProxyDummy_PaymentsEscrow","result":{"address":"0xF39FD65373870fcb5868F7458d8d84485E5Bf890","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setPauseGuardian","futureId":"Controller#Controller.setPauseGuardian","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Controller#Controller.setPauseGuardian","networkInteraction":{"data":"0x48bde20c00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Controller#Controller.setPauseGuardian","networkInteractionId":1,"nonce":552,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"222360000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x926847427742ab0047f7056be7cae6a83e0f6fc537fb430bc50cdc719059f776"},"type":"TRANSACTION_SEND"} +{"futureId":"Controller#Controller.setPauseGuardian","hash":"0x926847427742ab0047f7056be7cae6a83e0f6fc537fb430bc50cdc719059f776","networkInteractionId":1,"receipt":{"blockHash":"0xb0f86a559682a45f56cb41041d8f932d3cdc905196d94ffe5407c5154c8d51c1","blockNumber":82177476,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x","logIndex":1,"topics":["0x0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Controller#Controller.setPauseGuardian","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"transferOwnership","futureId":"Controller#Controller.transferOwnership","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Controller#Controller.transferOwnership","networkInteraction":{"data":"0xf2fde38b000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Controller#Controller.transferOwnership","networkInteractionId":1,"nonce":553,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"217900000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x8973c2ac20958068d8292af8587c979c3d504a55fb0165f835cac502918824ed"},"type":"TRANSACTION_SEND"} +{"futureId":"Controller#Controller.transferOwnership","hash":"0x8973c2ac20958068d8292af8587c979c3d504a55fb0165f835cac502918824ed","networkInteractionId":1,"receipt":{"blockHash":"0xd2308faec84b43992fc7ac43c75929ea587f9ed63dca3357d2685e11ec8f0c62","blockNumber":82177492,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x","logIndex":0,"topics":["0x76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Controller#Controller.transferOwnership","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"transferOwnership","futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","networkInteraction":{"data":"0xf2fde38b000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","networkInteractionId":1,"nonce":554,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"211820000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x94ba70c3305da1c2850e0fd0482ca86d033f91a6f82272a3fa8d7c03b1a19702"},"type":"TRANSACTION_SEND"} +{"args":["0xade6b8eb69a49b56929c1d4f4b428d791861db6f"],"artifactId":"GraphToken#GraphToken","dependencies":["GraphToken#GraphToken"],"functionName":"initialize","futureId":"GraphToken#encodeFunctionCall(GraphToken#GraphToken.initialize)","result":"0xc4d66de8000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","constructorArgs":["0x60eE16fc2C4729343C7B3Ab9B322b2C6CcfbC681","0xade6b8eb69a49b56929c1d4f4b428d791861db6f","0x"],"contractName":"TransparentUpgradeableProxy","dependencies":["HorizonProxies#OZProxyDummy_GraphPayments"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","networkInteraction":{"data":"0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000060ee16fc2c4729343c7b3ab9b322b2c6ccfbc681000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","networkInteractionId":1,"nonce":555,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"203040000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xab7001383d7cf18ec79633ba203778308bfe93999fcf5c33f100ea1eb728ffaa"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","hash":"0xab7001383d7cf18ec79633ba203778308bfe93999fcf5c33f100ea1eb728ffaa","networkInteractionId":1,"receipt":{"blockHash":"0x72df9ece6fcad9f332fc3a794990a9932c1e00ccf422e6d319961366c0383495","blockNumber":82177523,"contractAddress":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","logs":[{"address":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","data":"0x","logIndex":3,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x00000000000000000000000060ee16fc2c4729343c7b3ab9b322b2c6ccfbc681"]},{"address":"0xbb29b876AA2faCEb3af83d768CB03dd3BFF03f5e","data":"0x","logIndex":4,"topics":["0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f"]},{"address":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","data":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb29b876aa2faceb3af83d768cb03dd3bff03f5e","logIndex":5,"topics":["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","result":{"address":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","constructorArgs":["0xF39FD65373870fcb5868F7458d8d84485E5Bf890","0xade6b8eb69a49b56929c1d4f4b428d791861db6f","0x"],"contractName":"TransparentUpgradeableProxy","dependencies":["HorizonProxies#OZProxyDummy_PaymentsEscrow"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","networkInteraction":{"data":"0x60a060405260405162000eb138038062000eb18339810160408190526200002691620003cd565b82816200003482826200009c565b505081604051620000459062000366565b6001600160a01b039091168152602001604051809103906000f08015801562000072573d6000803e3d6000fd5b506001600160a01b0316608052620000936200008d60805190565b62000102565b505050620004cb565b620000a78262000174565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115620000f457620000ef8282620001f4565b505050565b620000fe62000271565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014460008051602062000e91833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001718162000293565b50565b806001600160a01b03163b600003620001b057604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080846001600160a01b031684604051620002139190620004ad565b600060405180830381855af49150503d806000811462000250576040519150601f19603f3d011682016040523d82523d6000602084013e62000255565b606091505b50909250905062000268858383620002d6565b95945050505050565b3415620002915760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b038116620002bf57604051633173bdd160e11b815260006004820152602401620001a7565b8060008051602062000e91833981519152620001d3565b606082620002ef57620002e9826200033c565b62000335565b81511580156200030757506001600160a01b0384163b155b156200033257604051639996b31560e01b81526001600160a01b0385166004820152602401620001a7565b50805b9392505050565b8051156200034d5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b610524806200096d83390190565b80516001600160a01b03811681146200038c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003c4578181015183820152602001620003aa565b50506000910152565b600080600060608486031215620003e357600080fd5b620003ee8462000374565b9250620003fe6020850162000374565b60408501519092506001600160401b03808211156200041c57600080fd5b818601915086601f8301126200043157600080fd5b81518181111562000446576200044662000391565b604051601f8201601f19908116603f0116810190838211818310171562000471576200047162000391565b816040528281528960208487010111156200048b57600080fd5b6200049e836020830160208801620003a7565b80955050505050509250925092565b60008251620004c1818460208701620003a7565b9190910192915050565b608051610487620004e66000396000601001526104876000f3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007b576000356001600160e01b03191663278f794360e11b14610071576040516334ad5dbb60e21b815260040160405180910390fd5b610079610083565b565b6100796100b2565b6000806100933660048184610312565b8101906100a09190610352565b915091506100ae82826100c2565b5050565b6100796100bd61011d565b610155565b6100cb82610179565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156101155761011082826101f5565b505050565b6100ae61026b565b60006101507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015610174573d6000f35b3d6000fd5b806001600160a01b03163b6000036101b457604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516102129190610422565b600060405180830381855af49150503d806000811461024d576040519150601f19603f3d011682016040523d82523d6000602084013e610252565b606091505b509150915061026285838361028a565b95945050505050565b34156100795760405163b398979f60e01b815260040160405180910390fd5b60608261029f5761029a826102e9565b6102e2565b81511580156102b657506001600160a01b0384163b155b156102df57604051639996b31560e01b81526001600160a01b03851660048201526024016101ab565b50805b9392505050565b8051156102f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6000808585111561032257600080fd5b8386111561032f57600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561036557600080fd5b82356001600160a01b038116811461037c57600080fd5b9150602083013567ffffffffffffffff8082111561039957600080fd5b818501915085601f8301126103ad57600080fd5b8135818111156103bf576103bf61033c565b604051601f8201601f19908116603f011681019083821181831017156103e7576103e761033c565b8160405282815288602084870101111561040057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b818110156104435760208186018101518583015201610429565b50600092019182525091905056fea264697066735822122053869634917c3f506e9458e33de6974842d50d2f87cc565783db64cc7b8af3f264736f6c63430008140033608060405234801561001057600080fd5b5060405161052438038061052483398101604081905261002f916100be565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100678161006e565b50506100ee565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100d057600080fd5b81516001600160a01b03811681146100e757600080fd5b9392505050565b610427806100fd6000396000f3fe60806040526004361061004a5760003560e01c8063715018a61461004f5780638da5cb5b146100665780639623609d14610093578063ad3cb1cc146100a6578063f2fde38b146100e4575b600080fd5b34801561005b57600080fd5b50610064610104565b005b34801561007257600080fd5b506000546040516001600160a01b0390911681526020015b60405180910390f35b6100646100a1366004610272565b610118565b3480156100b257600080fd5b506100d7604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161008a919061038e565b3480156100f057600080fd5b506100646100ff3660046103a8565b610187565b61010c6101ca565b61011660006101f7565b565b6101206101ca565b60405163278f794360e11b81526001600160a01b03841690634f1ef28690349061015090869086906004016103c5565b6000604051808303818588803b15801561016957600080fd5b505af115801561017d573d6000803e3d6000fd5b5050505050505050565b61018f6101ca565b6001600160a01b0381166101be57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6101c7816101f7565b50565b6000546001600160a01b031633146101165760405163118cdaa760e01b81523360048201526024016101b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101c757600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561028757600080fd5b833561029281610247565b925060208401356102a281610247565b9150604084013567ffffffffffffffff808211156102bf57600080fd5b818601915086601f8301126102d357600080fd5b8135818111156102e5576102e561025c565b604051601f8201601f19908116603f0116810190838211818310171561030d5761030d61025c565b8160405282815289602084870101111561032657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b8181101561036e57602081850181015186830182015201610352565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006103a16020830184610348565b9392505050565b6000602082840312156103ba57600080fd5b81356103a181610247565b6001600160a01b03831681526040602082018190526000906103e990830184610348565b94935050505056fea2646970667358221220c1ca14a59ae9fe8f66625b7accc22e698394cc37b875cf375a41b9ced938f75264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000f39fd65373870fcb5868f7458d8d84485e5bf890000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","networkInteractionId":1,"nonce":556,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x4e06072395cbaa97b5684e02e90db9a90d627f28c7fba7bbc29395a6937ba71b"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","hash":"0x4e06072395cbaa97b5684e02e90db9a90d627f28c7fba7bbc29395a6937ba71b","networkInteractionId":1,"receipt":{"blockHash":"0xa7df78ebf3a95f01465193fabeb7cb5ef3c8a96b3f87bfc6e95f422b1e0a53cc","blockNumber":82177538,"contractAddress":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","logs":[{"address":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","data":"0x","logIndex":1,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x000000000000000000000000f39fd65373870fcb5868f7458d8d84485e5bf890"]},{"address":"0x6D892d831196E1Ad3779B97320b7091dE7d45053","data":"0x","logIndex":2,"topics":["0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f"]},{"address":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d892d831196e1ad3779b97320b7091de7d45053","logIndex":3,"topics":["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","result":{"address":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","hash":"0x94ba70c3305da1c2850e0fd0482ca86d033f91a6f82272a3fa8d7c03b1a19702","networkInteractionId":1,"receipt":{"blockHash":"0x409a8676bb58a489dc722e9d4c5b33c8fb4f06cad2eec0a2e4f31013d1d32c2e","blockNumber":82177508,"logs":[{"address":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","data":"0x","logIndex":2,"topics":["0x76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphProxyAdmin#GraphProxyAdmin.transferOwnership","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"BridgeEscrow#GraphProxy","constructorArgs":["0xbC846a82491A4b6Ee5fd841c60923019d99F6D0c","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"contractName":"GraphProxy","dependencies":["BridgeEscrow#BridgeEscrow","GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"BridgeEscrow#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"BridgeEscrow#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000bc846a82491a4b6ee5fd841c60923019d99f6d0c0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"BridgeEscrow#GraphProxy","networkInteractionId":1,"nonce":557,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x6765e678edba8a194b3a5bc9fd849f45c11514154f7de24b9bf9c6d059478e35"},"type":"TRANSACTION_SEND"} +{"futureId":"BridgeEscrow#GraphProxy","hash":"0x6765e678edba8a194b3a5bc9fd849f45c11514154f7de24b9bf9c6d059478e35","networkInteractionId":1,"receipt":{"blockHash":"0xe5472a7a4abb34f9705684195f85064132ff47f6302a612573a002391ecaf5ad","blockNumber":82177562,"contractAddress":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","logs":[{"address":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","data":"0x","logIndex":2,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da"]},{"address":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","data":"0x","logIndex":3,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000bc846a82491a4b6ee5fd841c60923019d99f6d0c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"BridgeEscrow#GraphProxy","result":{"address":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa"],"artifactId":"BridgeEscrow#BridgeEscrow","dependencies":["BridgeEscrow#BridgeEscrow","Controller#Controller"],"functionName":"initialize","futureId":"BridgeEscrow#encodeFunctionCall(BridgeEscrow#BridgeEscrow.initialize)","result":"0xc4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"Curation#GraphProxy","constructorArgs":["0x73A09b3A9C5531da3374A12a1282e40C3e2B7FA0","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"contractName":"GraphProxy","dependencies":["Curation#Curation","GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"Curation#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c00000000000000000000000073a09b3a9c5531da3374a12a1282e40c3e2b7fa00000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#GraphProxy","networkInteractionId":1,"nonce":558,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xc21dba5ebc3a1b84d0e6c979e0ee3f372c87f440355fcba23e7fd115870efada"},"type":"TRANSACTION_SEND"} +{"futureId":"Curation#GraphProxy","hash":"0xc21dba5ebc3a1b84d0e6c979e0ee3f372c87f440355fcba23e7fd115870efada","networkInteractionId":1,"receipt":{"blockHash":"0x52ed4a28b2c5b4bbc55bdc895f6409ab482ec27707afb17705c82435560e8301","blockNumber":82177577,"contractAddress":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","logs":[{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x","logIndex":3,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da"]},{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x","logIndex":4,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000073a09b3a9c5531da3374a12a1282e40c3e2b7fa0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#GraphProxy","result":{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","0xF1c0D12b4b4f6f0d66CE0A18A16876c9ca6D2E92",10000,1],"artifactId":"Curation#Curation","dependencies":["Curation#Curation","Controller#Controller","Curation#GraphCurationToken"],"functionName":"initialize","futureId":"Curation#encodeFunctionCall(Curation#Curation.initialize)","result":"0x4c8c7a440000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000f1c0d12b4b4f6f0d66ce0a18a16876c9ca6d2e9200000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000001","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"EpochManager#GraphProxy","constructorArgs":["0x039B22cEd4cDbF6Cd153F38ba7ae2731471e0542","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"contractName":"GraphProxy","dependencies":["EpochManager#EpochManager","GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"EpochManager#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"EpochManager#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000039b22ced4cdbf6cd153f38ba7ae2731471e05420000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"EpochManager#GraphProxy","networkInteractionId":1,"nonce":559,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x6dc94e70324af84c4dc6148706d1bede53bef42d83fb701ebbd9149b4f26c666"},"type":"TRANSACTION_SEND"} +{"args":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa",60],"artifactId":"EpochManager#EpochManager","dependencies":["EpochManager#EpochManager","Controller#Controller"],"functionName":"initialize","futureId":"EpochManager#encodeFunctionCall(EpochManager#EpochManager.initialize)","result":"0xcd6dc6870000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000000000000000000000000000000000000000003c","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"args":["0xed734418922426bf2cc8783754bd80fc4d441a4dbe994549aee8a2f03136fcdb","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","networkInteraction":{"data":"0xe0e99292ed734418922426bf2cc8783754bd80fc4d441a4dbe994549aee8a2f03136fcdb0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","networkInteractionId":1,"nonce":560,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xf45d81ed330840d6970a16933babea25a5af19dbeee69108dc986f7158d93356"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","hash":"0xf45d81ed330840d6970a16933babea25a5af19dbeee69108dc986f7158d93356","networkInteractionId":1,"receipt":{"blockHash":"0xc00e89b3c2298ee25569d2a9c2418bacf011a87ce00ac95f67322b27ef792f43","blockNumber":82177607,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","logIndex":3,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xed734418922426bf2cc8783754bd80fc4d441a4dbe994549aee8a2f03136fcdb"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphToken#GraphProxy","constructorArgs":["0x21Ee267Efe20A7E846964D3f9E28F7e81d72547e","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"contractName":"GraphProxy","dependencies":["GraphToken#GraphToken","GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"GraphToken#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c00000000000000000000000021ee267efe20a7e846964d3f9e28f7e81d72547e0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphProxy","networkInteractionId":1,"nonce":561,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x8b106356a522f264deb4e9bf75f3f7f97fb484f8a9c9e915a591431fcdf13e56"},"type":"TRANSACTION_SEND"} +{"artifactId":"GraphTokenGateway#GraphProxy","constructorArgs":["0x2f3f6fbAD807800da2d1ABC9c949c45Bc1C81541","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"contractName":"GraphProxy","dependencies":["GraphTokenGateway#GraphTokenGateway","GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"GraphTokenGateway#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c0000000000000000000000002f3f6fbad807800da2d1abc9c949c45bc1c815410000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphProxy","networkInteractionId":1,"nonce":562,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x5dd8bf388f54a96838f1232e96a415f458b5a58ca729ce127e449de332ccbf8b"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphTokenGateway#GraphProxy","hash":"0x5dd8bf388f54a96838f1232e96a415f458b5a58ca729ce127e449de332ccbf8b","networkInteractionId":1,"receipt":{"blockHash":"0x5e42be7c912fa1eaf370a9e33204494538ec7c81f21eac861fb58673aba983bf","blockNumber":82177637,"contractAddress":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","logs":[{"address":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","data":"0x","logIndex":5,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da"]},{"address":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","data":"0x","logIndex":6,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000002f3f6fbad807800da2d1abc9c949c45bc1c81541"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphProxy","result":{"address":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa"],"artifactId":"GraphTokenGateway#GraphTokenGateway","dependencies":["GraphTokenGateway#GraphTokenGateway","Controller#Controller"],"functionName":"initialize","futureId":"GraphTokenGateway#encodeFunctionCall(GraphTokenGateway#GraphTokenGateway.initialize)","result":"0xc4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments","dependencies":["HorizonProxies#TransparentUpgradeableProxy_GraphPayments"],"emitterAddress":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","eventIndex":0,"eventName":"AdminChanged","futureId":"HorizonProxies#TransparentUpgradeableProxy_GraphPayments_AdminChanged","nameOrIndex":"newAdmin","result":"0xbb29b876AA2faCEb3af83d768CB03dd3BFF03f5e","strategy":"basic","strategyConfig":{},"txToReadFrom":"0xab7001383d7cf18ec79633ba203778308bfe93999fcf5c33f100ea1eb728ffaa","type":"READ_EVENT_ARGUMENT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","dependencies":["HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow"],"emitterAddress":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","eventIndex":0,"eventName":"AdminChanged","futureId":"HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow_AdminChanged","nameOrIndex":"newAdmin","result":"0x6D892d831196E1Ad3779B97320b7091dE7d45053","strategy":"basic","strategyConfig":{},"txToReadFrom":"0x4e06072395cbaa97b5684e02e90db9a90d627f28c7fba7bbc29395a6937ba71b","type":"READ_EVENT_ARGUMENT_EXECUTION_STATE_INITIALIZE"} +{"args":["0x88cae14a9889b95b4cfd9472fc7dcbca2da791846a1e314bac9c1f8a234cbf9f","0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","HorizonProxies#TransparentUpgradeableProxy_GraphPayments"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"HorizonProxies#setContractProxy_GraphPayments","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","networkInteraction":{"data":"0xe0e9929288cae14a9889b95b4cfd9472fc7dcbca2da791846a1e314bac9c1f8a234cbf9f000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","networkInteractionId":1,"nonce":563,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x9eb2502dab3d648c850fabd89bc1c3486fa63cbcae80944cb5db77c88bca3a63"},"type":"TRANSACTION_SEND"} +{"args":["0x628f67391f8b955553cabfadbf5f1b6a31d2a2d0fea175f5594af9d40b0bedc9","0x5904ab9c7806FCC7634F1DcDBec544eEa7490634"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","networkInteraction":{"data":"0xe0e99292628f67391f8b955553cabfadbf5f1b6a31d2a2d0fea175f5594af9d40b0bedc90000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea7490634","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","networkInteractionId":1,"nonce":564,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xaba39186fa8a30518e066c00ccd1eb3e0c2997d551988a7e530772c6c689cca1"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","hash":"0xaba39186fa8a30518e066c00ccd1eb3e0c2997d551988a7e530772c6c689cca1","networkInteractionId":1,"receipt":{"blockHash":"0x169f5fddc08f24923f0f20d168c3764088c670f6037890d2770633db034be2db","blockNumber":82177667,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea7490634","logIndex":0,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x628f67391f8b955553cabfadbf5f1b6a31d2a2d0fea175f5594af9d40b0bedc9"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#setContractProxy_PaymentsEscrow","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"RewardsManager#GraphProxy","constructorArgs":["0xE7ed8F3e83a10a74CBfaDdC7596CBb79c4eccA17","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"contractName":"GraphProxy","dependencies":["RewardsManager#RewardsManager","GraphProxyAdmin#GraphProxyAdmin"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"RewardsManager#GraphProxy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#GraphProxy","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c000000000000000000000000e7ed8f3e83a10a74cbfaddc7596cbb79c4ecca170000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#GraphProxy","networkInteractionId":1,"nonce":565,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x20d17ae698896b0c0701926e86765b8b0c3e0c0d135d955f225a48d89132404a"},"type":"TRANSACTION_SEND"} +{"futureId":"RewardsManager#GraphProxy","hash":"0x20d17ae698896b0c0701926e86765b8b0c3e0c0d135d955f225a48d89132404a","networkInteractionId":1,"receipt":{"blockHash":"0x91fde94090b56e22f4c697c17da9743e4725a227d0466217005e12085cf699f9","blockNumber":82177682,"contractAddress":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","logs":[{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x","logIndex":0,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da"]},{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x","logIndex":1,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000e7ed8f3e83a10a74cbfaddc7596cbb79c4ecca17"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#GraphProxy","result":{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa"],"artifactId":"RewardsManager#RewardsManager","dependencies":["RewardsManager#RewardsManager","Controller#Controller"],"functionName":"initialize","futureId":"RewardsManager#encodeFunctionCall(RewardsManager#RewardsManager.initialize)","result":"0xc4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"futureId":"EpochManager#GraphProxy","hash":"0x6dc94e70324af84c4dc6148706d1bede53bef42d83fb701ebbd9149b4f26c666","networkInteractionId":1,"receipt":{"blockHash":"0xe9ddf67223f99e54a8f0a3b098e73dbe71fb3286da27272e3caa0bdb8b4eb76d","blockNumber":82177592,"contractAddress":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","logs":[{"address":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","data":"0x","logIndex":4,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da"]},{"address":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","data":"0x","logIndex":5,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000039b22ced4cdbf6cd153f38ba7ae2731471e0542"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"EpochManager#GraphProxy","result":{"address":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphToken#GraphProxy","hash":"0x8b106356a522f264deb4e9bf75f3f7f97fb484f8a9c9e915a591431fcdf13e56","networkInteractionId":1,"receipt":{"blockHash":"0x4c712f556a39a58da8fe9da1d73666c45b9e98e876700dedfba09801341cb67e","blockNumber":82177622,"contractAddress":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","logs":[{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":11,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da"]},{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":12,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000021ee267efe20a7e846964d3f9e28f7e81d72547e"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphProxy","result":{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","hash":"0x9eb2502dab3d648c850fabd89bc1c3486fa63cbcae80944cb5db77c88bca3a63","networkInteractionId":1,"receipt":{"blockHash":"0x377b496e138ad2f34a156ee77243204bcb6a14392f056a80c158538b49ac07a1","blockNumber":82177652,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f","logIndex":0,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x88cae14a9889b95b4cfd9472fc7dcbca2da791846a1e314bac9c1f8a234cbf9f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#setContractProxy_GraphPayments","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"BridgeEscrow#BridgeEscrow_Instance","contractAddress":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","contractName":"BridgeEscrow_Instance","dependencies":["BridgeEscrow#GraphProxy"],"futureId":"BridgeEscrow#BridgeEscrow_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0xbC846a82491A4b6Ee5fd841c60923019d99F6D0c","0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","0xc4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","BridgeEscrow#BridgeEscrow","BridgeEscrow#GraphProxy","BridgeEscrow#encodeFunctionCall(BridgeEscrow#BridgeEscrow.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"acceptProxyAndCall","futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e000000000000000000000000bc846a82491a4b6ee5fd841c60923019d99f6d0c000000000000000000000000d7c55208d82ea44386cbae9f64d6af60c6feea7900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":566,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x41e5f6ad996a801d1c91ce36afc151d525ee20003f423b66594a1a27d32b30b2"},"type":"TRANSACTION_SEND"} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x41e5f6ad996a801d1c91ce36afc151d525ee20003f423b66594a1a27d32b30b2","networkInteractionId":1,"receipt":{"blockHash":"0x6cd9a697e1ca8b0bdb978ae12806456e3b8950db7acfdef8a5ca2b5669cc743b","blockNumber":82177710,"logs":[{"address":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","data":"0x","logIndex":3,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000bc846a82491a4b6ee5fd841c60923019d99f6d0c"]},{"address":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","data":"0x","logIndex":4,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000bc846a82491a4b6ee5fd841c60923019d99f6d0c","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xd7c55208D82ea44386CbaE9f64D6af60c6Feea79","data":"0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","logIndex":5,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"BridgeEscrow#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"Curation#Curation_Instance","contractAddress":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","contractName":"Curation_Instance","dependencies":["Curation#GraphProxy"],"futureId":"Curation#Curation_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0x73A09b3A9C5531da3374A12a1282e40C3e2B7FA0","0x4594A5915B3AAa78CdF6273a76678855Ca675860","0x4c8c7a440000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000f1c0d12b4b4f6f0d66ce0a18a16876c9ca6d2e9200000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000001"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","Curation#Curation","Curation#GraphProxy","Curation#encodeFunctionCall(Curation#Curation.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"acceptProxyAndCall","futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e00000000000000000000000073a09b3a9c5531da3374a12a1282e40c3e2b7fa00000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000844c8c7a440000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000f1c0d12b4b4f6f0d66ce0a18a16876c9ca6d2e920000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":567,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x83fabf287402d1e1d759e417928c911c3253f4d8d64e4af799229026902fcd37"},"type":"TRANSACTION_SEND"} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x83fabf287402d1e1d759e417928c911c3253f4d8d64e4af799229026902fcd37","networkInteractionId":1,"receipt":{"blockHash":"0xb966d585029d67d6d0e7dec84cd1fbfaca6be4335327b24e3a787066b3a58016","blockNumber":82177726,"logs":[{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x","logIndex":6,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000073a09b3a9c5531da3374a12a1282e40c3e2b7fa0"]},{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x","logIndex":7,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x00000000000000000000000073a09b3a9c5531da3374a12a1282e40c3e2b7fa0","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","logIndex":8,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]},{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001364656661756c7452657365727665526174696f00000000000000000000000000","logIndex":9,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]},{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000156375726174696f6e54617850657263656e746167650000000000000000000000","logIndex":10,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]},{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000166d696e696d756d4375726174696f6e4465706f73697400000000000000000000","logIndex":11,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]},{"address":"0x4594A5915B3AAa78CdF6273a76678855Ca675860","data":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000136375726174696f6e546f6b656e4d617374657200000000000000000000000000","logIndex":12,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Curation#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"EpochManager#EpochManager_Instance","contractAddress":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","contractName":"EpochManager_Instance","dependencies":["EpochManager#GraphProxy"],"futureId":"EpochManager#EpochManager_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0x039B22cEd4cDbF6Cd153F38ba7ae2731471e0542","0x7975475801BEf845f10Ce7784DC69aB1e0344f11","0xcd6dc6870000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000000000000000000000000000000000000000003c"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","EpochManager#EpochManager","EpochManager#GraphProxy","EpochManager#encodeFunctionCall(EpochManager#EpochManager.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"acceptProxyAndCall","futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e000000000000000000000000039b22ced4cdbf6cd153f38ba7ae2731471e05420000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f1100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044cd6dc6870000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":568,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x143b4fe4bb79b41128ec9ab5541f3df8378b33ff00092740a8e8be83101e0862"},"type":"TRANSACTION_SEND"} +{"args":["0x21Ee267Efe20A7E846964D3f9E28F7e81d72547e","0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","0xc4d66de8000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","GraphToken#GraphToken","GraphToken#GraphProxy","GraphToken#encodeFunctionCall(GraphToken#GraphToken.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"acceptProxyAndCall","futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e00000000000000000000000021ee267efe20a7e846964d3f9e28f7e81d72547e0000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd34070200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":569,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xbd3ff6dc735aa70e940251a37bc52d1ad0e19b308a62bea4f371d5f8e2339f6e"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0xbd3ff6dc735aa70e940251a37bc52d1ad0e19b308a62bea4f371d5f8e2339f6e","networkInteractionId":1,"receipt":{"blockHash":"0x19be0cd6a1bdb4f878577b5be434af6b01ad9c86253aa1f147ff5dc5d91d3635","blockNumber":82177756,"logs":[{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":1,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000021ee267efe20a7e846964d3f9e28f7e81d72547e"]},{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":2,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x00000000000000000000000021ee267efe20a7e846964d3f9e28f7e81d72547e","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x0000000000000000000000000000000000000000000000000000000000000000","logIndex":3,"topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f"]},{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":4,"topics":["0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6","0x000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","contractName":"GraphToken_Instance","dependencies":["GraphToken#GraphProxy"],"futureId":"GraphToken#GraphToken_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0x2f3f6fbAD807800da2d1ABC9c949c45Bc1C81541","0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","0xc4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","GraphTokenGateway#GraphTokenGateway","GraphTokenGateway#GraphProxy","GraphTokenGateway#encodeFunctionCall(GraphTokenGateway#GraphTokenGateway.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"acceptProxyAndCall","futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e0000000000000000000000002f3f6fbad807800da2d1abc9c949c45bc1c81541000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":570,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x1ad6220ccafc61a75a5666e6208851932c8d7e32dc22bcf149ac4c93abc3955a"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x1ad6220ccafc61a75a5666e6208851932c8d7e32dc22bcf149ac4c93abc3955a","networkInteractionId":1,"receipt":{"blockHash":"0x8255289694c31481a4d2f970b3fd8bd447e0e47f0d474f3a7b032b69fbdcb2d0","blockNumber":82177770,"logs":[{"address":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","data":"0x","logIndex":0,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000002f3f6fbad807800da2d1abc9c949c45bc1c81541"]},{"address":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","data":"0x","logIndex":1,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000002f3f6fbad807800da2d1abc9c949c45bc1c81541","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","data":"0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","logIndex":2,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphTokenGateway#GraphTokenGateway_Instance","contractAddress":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","contractName":"GraphTokenGateway_Instance","dependencies":["GraphTokenGateway#GraphProxy"],"futureId":"GraphTokenGateway#GraphTokenGateway_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#ProxyAdmin_GraphPayments","contractAddress":"0xbb29b876AA2faCEb3af83d768CB03dd3BFF03f5e","contractName":"ProxyAdmin","dependencies":["HorizonProxies#TransparentUpgradeableProxy_GraphPayments_AdminChanged"],"futureId":"HorizonProxies#ProxyAdmin_GraphPayments","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonProxies#ProxyAdmin_PaymentsEscrow","contractAddress":"0x6D892d831196E1Ad3779B97320b7091dE7d45053","contractName":"ProxyAdmin","dependencies":["HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow_AdminChanged"],"futureId":"HorizonProxies#ProxyAdmin_PaymentsEscrow","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":["0xE7ed8F3e83a10a74CBfaDdC7596CBb79c4eccA17","0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","0xc4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","RewardsManager#RewardsManager","RewardsManager#GraphProxy","RewardsManager#encodeFunctionCall(RewardsManager#RewardsManager.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"acceptProxyAndCall","futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteraction":{"data":"0x07ebde0e000000000000000000000000e7ed8f3e83a10a74cbfaddc7596cbb79c4ecca17000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe7500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","networkInteractionId":1,"nonce":571,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x3b2196e0f3f04807ac248fce393cc53b39e7cd015239e5ec583dfe4c21906a2c"},"type":"TRANSACTION_SEND"} +{"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","contractName":"RewardsManager_Instance","dependencies":["RewardsManager#GraphProxy"],"futureId":"RewardsManager#RewardsManager_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x143b4fe4bb79b41128ec9ab5541f3df8378b33ff00092740a8e8be83101e0862","networkInteractionId":1,"receipt":{"blockHash":"0x73d11df25f3b7d0afc5824cf20d631705ce1dc3e84859dcda3439d9d92996599","blockNumber":82177741,"logs":[{"address":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","data":"0x","logIndex":0,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000039b22ced4cdbf6cd153f38ba7ae2731471e0542"]},{"address":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","data":"0x","logIndex":1,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000039b22ced4cdbf6cd153f38ba7ae2731471e0542","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","data":"0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","logIndex":2,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]},{"address":"0x7975475801BEf845f10Ce7784DC69aB1e0344f11","data":"0x000000000000000000000000000000000000000000000000000000000000003c","logIndex":3,"topics":["0x25ddd6f00038d5eac0051df83c6084f140a01586f092e2728d1ed781c9ce2441","0x0000000000000000000000000000000000000000000000000000000000000001"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"EpochManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","hash":"0x3b2196e0f3f04807ac248fce393cc53b39e7cd015239e5ec583dfe4c21906a2c","networkInteractionId":1,"receipt":{"blockHash":"0xea47da320ac27f7f45979aad62300a2b9cb8250a272fd16d7a766e8c1d3d8049","blockNumber":82177785,"logs":[{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x","logIndex":0,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000e7ed8f3e83a10a74cbfaddc7596cbb79c4ecca17"]},{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x","logIndex":1,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000e7ed8f3e83a10a74cbfaddc7596cbb79c4ecca17","0x0000000000000000000000000000000000000000000000000000000000000000"]},{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca","logIndex":2,"topics":["0x4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f70"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#GraphProxyAdmin~GraphProxyAdmin.acceptProxyAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f","0x4594A5915B3AAa78CdF6273a76678855Ca675860"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","Curation#Curation_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_Curation","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","networkInteraction":{"data":"0xe0e99292e6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f0000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","networkInteractionId":1,"nonce":572,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xa5a9c473d42a65567e4fd38a90e0b5c15512ba417f1c4bffc4f28341f96c3e7f"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","hash":"0xa5a9c473d42a65567e4fd38a90e0b5c15512ba417f1c4bffc4f28341f96c3e7f","networkInteractionId":1,"receipt":{"blockHash":"0xdbc65ab325b085e410ad877403fdbcb21395a1bcf9ab8cd017143c23715c9c0c","blockNumber":82177811,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860","logIndex":0,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xe6876326c1291dfcbbd3864a6816d698cd591defc7aa2153d7f9c4c04016c89f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_Curation","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f67063","0x7975475801BEf845f10Ce7784DC69aB1e0344f11"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","EpochManager#EpochManager_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","networkInteraction":{"data":"0xe0e99292c713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f670630000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f11","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","networkInteractionId":1,"nonce":573,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x3d94c728a1d4175b5b2955de279f7aa3d6b1ece3c2adea3297e43238157eb1ed"},"type":"TRANSACTION_SEND"} +{"args":["0xade6b8eb69a49b56929c1d4f4b428d791861db6f",{"_kind":"bigint","value":"10000000000000000000000000000"}],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","dependencies":["GraphToken#GraphToken_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"mint","futureId":"GraphToken#GraphToken_Instance.mint","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken_Instance.mint","networkInteraction":{"data":"0x40c10f19000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f0000000000000000000000000000000000000000204fce5e3e25026110000000","id":1,"to":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken_Instance.mint","networkInteractionId":1,"nonce":574,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x2d833fa2b1148bc470e8743739c5877a34cda5b735d5014997e4d219d174804a"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphToken#GraphToken_Instance.mint","hash":"0x2d833fa2b1148bc470e8743739c5877a34cda5b735d5014997e4d219d174804a","networkInteractionId":1,"receipt":{"blockHash":"0x9f45c5fe448f38c5b686added8b8f23b09cfdc970a1546aea09f9275bd38e8be","blockNumber":82177841,"logs":[{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x0000000000000000000000000000000000000000204fce5e3e25026110000000","logIndex":0,"topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken_Instance.mint","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":[],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","dependencies":["GraphToken#GraphToken_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"renounceMinter","futureId":"GraphToken#GraphToken_Instance.renounceMinter","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","networkInteraction":{"data":"0x98650275","id":1,"to":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","networkInteractionId":1,"nonce":575,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xae0a40a2fadc29ff53ce697048a72d5e0b9a124c0c05ca4b59a56a16e9d2270b"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","hash":"0xae0a40a2fadc29ff53ce697048a72d5e0b9a124c0c05ca4b59a56a16e9d2270b","networkInteractionId":1,"receipt":{"blockHash":"0xbe7ab7e7674636bb1b28545388b6afafd829bfaaf3fb3ae86ec8a6dbcb4fe4e3","blockNumber":82177856,"logs":[{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":4,"topics":["0xe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb66692","0x000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken_Instance.renounceMinter","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0"],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","dependencies":["GraphToken#GraphToken_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"transferOwnership","futureId":"GraphToken#GraphToken_Instance.transferOwnership","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","networkInteraction":{"data":"0xf2fde38b000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0","id":1,"to":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","networkInteractionId":1,"nonce":576,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x45bafcda1fabc5ba82fc4aa2aa8f11fdffdf41e84f06c60aba1f521e8e393fd2"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","hash":"0x45bafcda1fabc5ba82fc4aa2aa8f11fdffdf41e84f06c60aba1f521e8e393fd2","networkInteractionId":1,"receipt":{"blockHash":"0x205ac6b84fdcc0e16b04ae8c408545384912f8ef5ba11e3bc0b461db02f8ac9e","blockNumber":82177871,"logs":[{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":0,"topics":["0x76563ad561b7036ae716b9b25cb521b21463240f104c97e12f25877f2235f33d","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ffcf8fdee72ac11b5c542428b35eef5769c409f0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#GraphToken_Instance.transferOwnership","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC"],"artifactId":"GraphTokenGateway#GraphTokenGateway_Instance","contractAddress":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","dependencies":["GraphTokenGateway#GraphTokenGateway_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setPauseGuardian","futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","networkInteraction":{"data":"0x48bde20c00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc","id":1,"to":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","networkInteractionId":1,"nonce":577,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x5cc12d2309f4850d5a964f46c54a07382fff89dba7e591b3d280c3e370df4268"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","hash":"0x5cc12d2309f4850d5a964f46c54a07382fff89dba7e591b3d280c3e370df4268","networkInteractionId":1,"receipt":{"blockHash":"0x823c9ca81f046e8fb494e6a777f3dae9895f9883c77d73c239920dd64c532473","blockNumber":82177886,"logs":[{"address":"0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D","data":"0x","logIndex":0,"topics":["0x0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphTokenGateway#GraphTokenGateway_Instance.setPauseGuardian","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":[{"_kind":"bigint","value":"114155251141552511415"}],"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","dependencies":["RewardsManager#RewardsManager_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setIssuancePerBlock","futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","networkInteraction":{"data":"0x1156bdc10000000000000000000000000000000000000000000000063038ec17c1be19b7","id":1,"to":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","networkInteractionId":1,"nonce":578,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x82db5ee4b00b8c346da57f15ed99ec28be01925a13982f92bf48092d6d7627be"},"type":"TRANSACTION_SEND"} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","hash":"0x82db5ee4b00b8c346da57f15ed99ec28be01925a13982f92bf48092d6d7627be","networkInteractionId":1,"receipt":{"blockHash":"0x15dfd982885eed8944fdab5e4995b31d1f2deb9eb4c4a0d07f2f9029490e6962","blockNumber":82177901,"logs":[{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001069737375616e6365506572426c6f636b00000000000000000000000000000000","logIndex":0,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager_Instance.setIssuancePerBlock","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xd03ea8624C8C5987235048901fB614fDcA89b117"],"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","dependencies":["RewardsManager#RewardsManager_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setSubgraphAvailabilityOracle","futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","networkInteraction":{"data":"0x0903c094000000000000000000000000d03ea8624c8c5987235048901fb614fdca89b117","id":1,"to":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","networkInteractionId":1,"nonce":579,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xf7cbe8cadc96b07c6986923c00168ee12c6ff1435330fed1af982858042b7852"},"type":"TRANSACTION_SEND"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","hash":"0xf7cbe8cadc96b07c6986923c00168ee12c6ff1435330fed1af982858042b7852","networkInteractionId":1,"receipt":{"blockHash":"0xf95b897a81bb7438d11c9c1bc54aa1b18a6b162126bf80e0d4a261df493391a5","blockNumber":82177916,"logs":[{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a7375626772617068417661696c6162696c6974794f7261636c65000000000000","logIndex":3,"topics":["0x96d5a4b4edf1cefd0900c166d64447f8da1d01d1861a6a60894b5b82a2c15c3c"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphAvailabilityOracle","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x0000000000000000000000000000000000000000"],"artifactId":"RewardsManager#RewardsManager_Instance","contractAddress":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","dependencies":["RewardsManager#RewardsManager_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setSubgraphService","futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","networkInteraction":{"data":"0x93a90a1e0000000000000000000000000000000000000000000000000000000000000000","id":1,"to":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","networkInteractionId":1,"nonce":580,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x257cb5b9342e5f80abc477541ee23abbc1598a334b3d591c8ac99110240ead2f"},"type":"TRANSACTION_SEND"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","hash":"0x257cb5b9342e5f80abc477541ee23abbc1598a334b3d591c8ac99110240ead2f","networkInteractionId":1,"receipt":{"blockHash":"0xc7e6de2316c21eb05ea2fcab1d8ed7bc112f08ef7cd934f9971311fd89bc2fc9","blockNumber":82177932,"logs":[{"address":"0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75","data":"0x","logIndex":0,"topics":["0x97befc0afcf2bace352f077aea9873c9552fc2e5ab26874f356006fdf9da4ede","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"RewardsManager#RewardsManager_Instance.setSubgraphService","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","hash":"0x3d94c728a1d4175b5b2955de279f7aa3d6b1ece3c2adea3297e43238157eb1ed","networkInteractionId":1,"receipt":{"blockHash":"0xb836f2900488a3ca46571b37ba80d65e45977a95502239d693cf7dcbad6b69e3","blockNumber":82177826,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f11","logIndex":6,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xc713c3df6d14cdf946460395d09af88993ee2b948b1a808161494e32c5f67063"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_EpochManager","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0","0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","GraphTokenGateway#GraphTokenGateway_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","networkInteraction":{"data":"0xe0e99292d362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","networkInteractionId":1,"nonce":581,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x8cf4ad7e1ae09e84d96aa3452b92113378935070c5367e6e0a52b0fcdc000ef6"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","hash":"0x8cf4ad7e1ae09e84d96aa3452b92113378935070c5367e6e0a52b0fcdc000ef6","networkInteractionId":1,"receipt":{"blockHash":"0xaa9d06da577568e972139e7f62c38d1dba246336063d014474209214cf2006a7","blockNumber":82177955,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d","logIndex":7,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0xd362cac9cb75c10d67bcc0b7eeb0b1ef48bb5420b556c092d4fd7f758816fcf0"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c53180761","0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","RewardsManager#RewardsManager_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","networkInteraction":{"data":"0xe0e99292966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c53180761000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","networkInteractionId":1,"nonce":582,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x76d9faa85811441e569c5b835ede5d416c3a3ba02921f1103d2cedaee62880fe"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","hash":"0x76d9faa85811441e569c5b835ede5d416c3a3ba02921f1103d2cedaee62880fe","networkInteractionId":1,"receipt":{"blockHash":"0xdfe1d7813754aed96a2ac85ad0df459d79472d57992a9be98a7dac6a0572c120","blockNumber":82177970,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75","logIndex":3,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x966f1e8d8d8014e05f6ec4a57138da9be1f7c5a7f802928a18072f7c53180761"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_RewardsManager","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xdC427a9aD72C0D9636c7B375E14C3dc39fFaf35D"],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","dependencies":["GraphToken#GraphToken_Instance","GraphTokenGateway#GraphTokenGateway_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"addMinter","futureId":"GraphToken#addMinterGateway","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#addMinterGateway","networkInteraction":{"data":"0x983b2d56000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d","id":1,"to":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#addMinterGateway","networkInteractionId":1,"nonce":583,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x5bb5e556b904302181aeaa326938c45e905c5db3cd189f8d90fd5697d773c8d9"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphToken#addMinterGateway","hash":"0x5bb5e556b904302181aeaa326938c45e905c5db3cd189f8d90fd5697d773c8d9","networkInteractionId":1,"receipt":{"blockHash":"0xa62b35117f728f6d68228453bfb94f84285eef0584844d0a02305fd7ca73331c","blockNumber":82177984,"logs":[{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":0,"topics":["0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6","0x000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#addMinterGateway","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xfA8c011255E691aeeB57Caa63ccD181E93BEfE75"],"artifactId":"GraphToken#GraphToken_Instance","contractAddress":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","dependencies":["GraphToken#GraphToken_Instance","RewardsManager#RewardsManager_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"addMinter","futureId":"GraphToken#addMinterRewardsManager","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphToken#addMinterRewardsManager","networkInteraction":{"data":"0x983b2d56000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75","id":1,"to":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphToken#addMinterRewardsManager","networkInteractionId":1,"nonce":584,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xb80549eb2dea0fb34554bd97601b3ad22cc6474434483c7eccfc01e978d37685"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphToken#addMinterRewardsManager","hash":"0xb80549eb2dea0fb34554bd97601b3ad22cc6474434483c7eccfc01e978d37685","networkInteractionId":1,"receipt":{"blockHash":"0xf8fa0e81638cbe4dff59d9b5e8b853b5580a1e4ae6d39df8e818e1bad443ee2a","blockNumber":82177999,"logs":[{"address":"0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702","data":"0x","logIndex":23,"topics":["0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6","0x000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphToken#addMinterRewardsManager","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247","0x1A1af8B44fD59dd2bbEb456D1b7604c7bd340702"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","GraphToken#GraphToken_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","networkInteraction":{"data":"0xe0e9929245fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc192470000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd340702","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","networkInteractionId":1,"nonce":585,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x4ff4dc5450737eb36320a79880a5e365e61d244037637a250ba0569079507aaf"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","hash":"0x4ff4dc5450737eb36320a79880a5e365e61d244037637a250ba0569079507aaf","networkInteractionId":1,"receipt":{"blockHash":"0x99cc0429b200d5161fec9b32dbdcf4e708366c0ef66696660f3196a193d4817c","blockNumber":82178021,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd340702","logIndex":9,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#setContractProxy_GraphToken","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphHorizon_Periphery#Dummy","constructorArgs":[],"contractName":"Dummy","dependencies":["GraphHorizon_Periphery#setContractProxy_EpochManager","GraphHorizon_Periphery#setContractProxy_RewardsManager","GraphHorizon_Periphery#setContractProxy_GraphToken","GraphHorizon_Periphery#setContractProxy_GraphTokenGateway","GraphHorizon_Periphery#setContractProxy_GraphProxyAdmin","GraphHorizon_Periphery#setContractProxy_Curation"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"GraphHorizon_Periphery#Dummy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphHorizon_Periphery#Dummy","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphHorizon_Periphery#Dummy","networkInteractionId":1,"nonce":586,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x950eac05b618a88ac09c2a5e4b022cf709ab46598bec57355323c5687fc38dd5"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphHorizon_Periphery#Dummy","hash":"0x950eac05b618a88ac09c2a5e4b022cf709ab46598bec57355323c5687fc38dd5","networkInteractionId":1,"receipt":{"blockHash":"0x810ceffc4b1418b9d282d414b465bb28e77cfe05a243c0ed7ac394255a98baed","blockNumber":82178038,"contractAddress":"0x3141000ae37361a525863D5cc4886799ed3FAFca","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphHorizon_Periphery#Dummy","result":{"address":"0x3141000ae37361a525863D5cc4886799ed3FAFca","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonProxies#GraphProxy_HorizonStaking","constructorArgs":["0x0000000000000000000000000000000000000000","0x0eb1325d7F1a188D5914fddb8566aE513A28D0da"],"contractName":"GraphProxy","dependencies":["GraphProxyAdmin#GraphProxyAdmin","GraphHorizon_Periphery#Dummy"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonProxies#GraphProxy_HorizonStaking","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","networkInteraction":{"data":"0x608060405234801561001057600080fd5b50604051610a12380380610a128339818101604052604081101561003357600080fd5b50805160209091015161004581610055565b61004e826100b3565b5050610137565b600061005f610111565b6000805160206109d2833981519152838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006100bd610124565b6000805160206109f2833981519152838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b6000805160206109d28339815191525490565b6000805160206109f28339815191525490565b61088c806101466000396000f3fe6080604052600436106100745760003560e01c80635c60da1b1161004e5780635c60da1b14610104578063623faf6114610119578063704b6c0214610196578063f851a440146101c957610083565b80633659cfe61461008b578063396f7b23146100be57806359fc20bb146100ef57610083565b36610083576100816101de565b005b6100816101de565b34801561009757600080fd5b50610081600480360360208110156100ae57600080fd5b50356001600160a01b031661029e565b3480156100ca57600080fd5b506100d36102d8565b604080516001600160a01b039092168252519081900360200190f35b3480156100fb57600080fd5b50610081610338565b34801561011057600080fd5b506100d3610393565b34801561012557600080fd5b506100816004803603602081101561013c57600080fd5b81019060208101813564010000000081111561015757600080fd5b82018360208201111561016957600080fd5b8035906020019184600183028401116401000000008311171561018b57600080fd5b5090925090506103e1565b3480156101a257600080fd5b50610081600480360360208110156101b957600080fd5b50356001600160a01b03166104f1565b3480156101d557600080fd5b506100d3610576565b6101e66105c0565b6001600160a01b0316336001600160a01b0316141561024c576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400604482015290519081900360640190fd5b6040516001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541636600083376000803684845af490503d806000843e81801561029a578184f35b8184fd5b6102a66105c0565b6001600160a01b0316336001600160a01b031614156102cd576102c8816105e5565b6102d5565b6102d56101de565b50565b60006102e26105c0565b6001600160a01b0316336001600160a01b031614806103195750610304610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610655565b9050610335565b6103356101de565b90565b6103406105c0565b6001600160a01b0316336001600160a01b031614806103775750610362610655565b6001600160a01b0316336001600160a01b0316145b156103895761038461067a565b610391565b6103916101de565b565b600061039d6105c0565b6001600160a01b0316336001600160a01b031614806103d457506103bf610655565b6001600160a01b0316336001600160a01b0316145b1561032d57610326610751565b6103e96105c0565b6001600160a01b0316336001600160a01b03161480610420575061040b610655565b6001600160a01b0316336001600160a01b0316145b156104e55761042d61067a565b6000610437610751565b6001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b50509050806104df576040805162461bcd60e51b815260206004820152601060248201526f125b5c1b0818d85b1b0819985a5b195960821b604482015290519081900360640190fd5b506104ed565b6104ed6101de565b5050565b6104f96105c0565b6001600160a01b0316336001600160a01b031614156102cd576001600160a01b03811661056d576040805162461bcd60e51b815260206004820152601e60248201527f41646d696e2063616e7420626520746865207a65726f20616464726573730000604482015290519081900360640190fd5b6102c881610776565b60006105806105c0565b6001600160a01b0316336001600160a01b031614806105b757506105a2610655565b6001600160a01b0316336001600160a01b0316145b1561032d576103265b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60006105ef610655565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c838155604051919250906001600160a01b0380851691908416907f980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a190600090a3505050565b7f9e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c5490565b6000610684610655565b90506001600160a01b0381166106e1576040805162461bcd60e51b815260206004820152601b60248201527f496d706c2063616e6e6f74206265207a65726f20616464726573730000000000604482015290519081900360640190fd5b336001600160a01b0382161461073e576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c792070656e64696e6720696d706c656d656e746174696f6e0000000000604482015290519081900360640190fd5b610747816107e6565b6102d560006105e5565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b60006107806105c0565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103838155604051919250906001600160a01b0380851691908416907f101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b90600090a3505050565b60006107f0610751565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc838155604051919250906001600160a01b0380851691908416907faa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da90600090a350505056fea264697066735822122041ce882775d17ef838c17f08249aa48a5f3ea1c65b581e69896452640b274de264736f6c63430007060033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61039e5eddc59e0b171f57125ab86bee043d9128098c3a6b9adb4f2e86333c2f6f8c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","networkInteractionId":1,"nonce":587,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x2d859ae24fcf0fad0c418daaeea6271d89dddb28d7c157b9f891cd5490ddb447"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","hash":"0x2d859ae24fcf0fad0c418daaeea6271d89dddb28d7c157b9f891cd5490ddb447","networkInteractionId":1,"receipt":{"blockHash":"0xb2fd4096ee4b0f99459c54fbca3166ea7a62c56bf16a5d3a649118a6c38a7bc5","blockNumber":82178055,"contractAddress":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","logs":[{"address":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","data":"0x","logIndex":1,"topics":["0x101b8081ff3b56bbf45deb824d86a3b0fd38b7e3dd42421105cf8abe9106db0b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da"]},{"address":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","data":"0x","logIndex":2,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#GraphProxy_HorizonStaking","result":{"address":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":["0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034","0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf"],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller","HorizonProxies#GraphProxy_HorizonStaking"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setContractProxy","futureId":"HorizonProxies#setContractProxy_HorizonStaking","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","networkInteraction":{"data":"0xe0e992921df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d1670340000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","networkInteractionId":1,"nonce":588,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xf80cfd15f181d133ae11a665d442403850ae1e33cece70ef661f41d35bac6103"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","hash":"0xf80cfd15f181d133ae11a665d442403850ae1e33cece70ef661f41d35bac6103","networkInteractionId":1,"receipt":{"blockHash":"0x2387a28cc054f3b0ae34f813d79b89f79132d42ed78f6ae45a2db8dcc69f5154","blockNumber":82178072,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","logIndex":0,"topics":["0x937cf566d78d4769ff0211a7d87a6bea51e1fc026fd4d3d8cd589f0e99b983bd","0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#setContractProxy_HorizonStaking","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonProxies#RegisteredDummy","constructorArgs":[],"contractName":"Dummy","dependencies":["HorizonProxies#setContractProxy_HorizonStaking","HorizonProxies#setContractProxy_GraphPayments","HorizonProxies#setContractProxy_PaymentsEscrow"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonProxies#RegisteredDummy","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonProxies#RegisteredDummy","networkInteraction":{"data":"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220e9552d0bd17028a389e7fe001355f436a4c48f8bbc01c19b8c400850f5a6b5ac64736f6c634300081b0033","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonProxies#RegisteredDummy","networkInteractionId":1,"nonce":589,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xf8a3e92f747810a08eb6de451a84bfe638e548cec635ce6d5ed37368d7443994"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonProxies#RegisteredDummy","hash":"0xf8a3e92f747810a08eb6de451a84bfe638e548cec635ce6d5ed37368d7443994","networkInteractionId":1,"receipt":{"blockHash":"0x3d27c72dbf1468c20f60dd1c2fe28285bfd46e925b7cbb073490b7b4dd0fb906","blockNumber":82178088,"contractAddress":"0xbDc6798b71a3B57fc79eF346d065de7477D3c366","logs":[],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonProxies#RegisteredDummy","result":{"address":"0xbDc6798b71a3B57fc79eF346d065de7477D3c366","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphPayments#GraphPayments","constructorArgs":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa",10000],"contractName":"GraphPayments","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"GraphPayments#GraphPayments","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphPayments#GraphPayments","networkInteraction":{"data":"0x6101e060405234801561001157600080fd5b5060405161132f38038061132f833981016040819052610030916104ee565b816001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b290610372565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e590610372565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e90610372565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015890610372565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019090610372565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb90610372565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020990610372565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024590610372565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a90610372565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a45061033a81620f4240101590565b819061035c5760405163d3097bcb60e01b815260040161007191815260200190565b506101c081905261036b610420565b505061058a565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103ad91815260200190565b602060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ee919061051a565b9050826001600160a01b0382166104195760405163218f5add60e11b8152600401610071919061053c565b5092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156104705760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146104cf5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146104e957600080fd5b919050565b6000806040838503121561050157600080fd5b61050a836104d2565b9150602083015190509250929050565b60006020828403121561052c57600080fd5b610535826104d2565b9392505050565b602081526000825180602084015260005b8181101561056a576020818601810151604086840101520161054d565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051610d086106276000396000818160560152610104015260005050600050506000505060005050600050506000505060005050600050506000818161012e015281816102c1015261035401526000818160d5015281816102220152818161025a0152818161029201526103f50152610d086000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80631d526e50146100515780636c69783a1461008b5780638129fc1c146100a0578063ac9650d8146100a8575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61009e6100993660046109ab565b6100c8565b005b61009e61047f565b6100bb6100b6366004610a06565b61058d565b6040516100829190610aa1565b6100fc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385610676565b6000610128847f0000000000000000000000000000000000000000000000000000000000000000610733565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637573ef4f87868a6040518463ffffffff1660e01b815260040161017c93929190610b21565b602060405180830381865afa158015610199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bd9190610b65565b905060006101cb8683610733565b90506000816101da8686610b94565b6101e49190610b94565b905086818082101561021757604051638bd93bad60e01b8152600481019290925260248201526044015b60405180910390fd5b5050610253846102447f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0316906107a1565b61028a86867f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190610806565b81156103e0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af115801561032d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103519190610ba7565b507f000000000000000000000000000000000000000000000000000000000000000060405163ca94b0e960e01b81526001600160a01b038a81166004830152888116602483015260448201859052919091169063ca94b0e990606401600060405180830381600087803b1580156103c757600080fd5b505af11580156103db573d6000803e3d6000fd5b505050505b60006103ec8289610bc9565b905061041989827f000000000000000000000000000000000000000000000000000000000000000061027a565b6040805182815260208101859052908101879052606081018690526001600160a01b0380891691908b169033907fb6dba03dcdcd7b7167b22bd6f1462a936eb55f4218b1d4dddff20bdec5703ca39060800160405180910390a450505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156104c55750825b905060008267ffffffffffffffff1660011480156104e25750303b155b9050811580156104f0575080155b1561050e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561053857845460ff60401b1916600160401b1785555b610540610841565b831561058657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b6040805160008152602081019091526060908267ffffffffffffffff8111156105b8576105b8610bdc565b6040519080825280602002602001820160405280156105eb57816020015b60608152602001906001900390816105d65790505b50915060005b8381101561066d576106483086868481811061060f5761060f610bf2565b90506020028101906106219190610c08565b8560405160200161063493929190610c56565b60405160208183030381529060405261084b565b83828151811061065a5761065a610bf2565b60209081029190910101526001016105f1565b50505b92915050565b801561072e576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190610ba7565b61072e5760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161020e565b505050565b600061074283620f4240101590565b80610755575061075582620f4240101590565b8383909161077f5760405163768bf0eb60e11b81526004810192909252602482015260440161020e565b50620f424090506107908385610c7d565b61079a9190610c94565b9392505050565b801561080257604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156107e957600080fd5b505af11580156107fd573d6000803e3d6000fd5b505050505b5050565b801561072e5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016106b3565b6108496108c1565b565b6060600080846001600160a01b0316846040516108689190610cb6565b600060405180830381855af49150503d80600081146108a3576040519150601f19603f3d011682016040523d82523d6000602084013e6108a8565b606091505b50915091506108b885838361090a565b95945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661084957604051631afcd79f60e31b815260040160405180910390fd5b60608261091f5761091a82610966565b61079a565b815115801561093657506001600160a01b0384163b155b1561095f57604051639996b31560e01b81526001600160a01b038516600482015260240161020e565b5092915050565b8051156109765780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146109a657600080fd5b919050565b600080600080600060a086880312156109c357600080fd5b8535600381106109d257600080fd5b94506109e06020870161098f565b9350604086013592506109f56060870161098f565b949793965091946080013592915050565b60008060208385031215610a1957600080fd5b823567ffffffffffffffff811115610a3057600080fd5b8301601f81018513610a4157600080fd5b803567ffffffffffffffff811115610a5857600080fd5b8560208260051b8401011115610a6d57600080fd5b6020919091019590945092505050565b60005b83811015610a98578181015183820152602001610a80565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015610b1557603f1987860301845281518051808752610af2816020890160208501610a7d565b601f01601f19169590950160209081019550938401939190910190600101610ac9565b50929695505050505050565b6001600160a01b038481168252831660208201526060810160038310610b5757634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b600060208284031215610b7757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067057610670610b7e565b600060208284031215610bb957600080fd5b8151801515811461079a57600080fd5b8181038181111561067057610670610b7e565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112610c1f57600080fd5b83018035915067ffffffffffffffff821115610c3a57600080fd5b602001915036819003821315610c4f57600080fd5b9250929050565b828482376000838201600081528351610c73818360208801610a7d565b0195945050505050565b808202811582820484141761067057610670610b7e565b600082610cb157634e487b7160e01b600052601260045260246000fd5b500490565b60008251610cc8818460208701610a7d565b919091019291505056fea2646970667358221220014e32010460d303e4961788506a40f57bf919f7e64f17c1db1f5dcfec869fbd64736f6c634300081b00330000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca0000000000000000000000000000000000000000000000000000000000002710","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphPayments#GraphPayments","networkInteractionId":1,"nonce":590,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x9c9f5448c154a8d46b3d5935177638b8b3ad68325521636b16887406b2ba5048"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphPayments#GraphPayments","hash":"0x9c9f5448c154a8d46b3d5935177638b8b3ad68325521636b16887406b2ba5048","networkInteractionId":1,"receipt":{"blockHash":"0x2d9565b9d4e1f9fe534a94a47254da24c94f579027f4e9467e8012e7b11b350f","blockNumber":82178104,"contractAddress":"0xf5B3661BbB8CD48571C7f41ba2D896a3589C9753","logs":[{"address":"0xf5B3661BbB8CD48571C7f41ba2D896a3589C9753","data":"0x000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f0000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea74906340000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f11000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da0000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860","logIndex":1,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x0000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd340702","0x0000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"]},{"address":"0xf5B3661BbB8CD48571C7f41ba2D896a3589C9753","data":"0x000000000000000000000000000000000000000000000000ffffffffffffffff","logIndex":2,"topics":["0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphPayments#GraphPayments","result":{"address":"0xf5B3661BbB8CD48571C7f41ba2D896a3589C9753","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"GraphPayments#GraphPayments_Instance","contractAddress":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","contractName":"GraphPayments","dependencies":["HorizonProxies#TransparentUpgradeableProxy_GraphPayments"],"futureId":"GraphPayments#GraphPayments_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonStakingExtension#HorizonStakingExtension","constructorArgs":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","0x0000000000000000000000000000000000000000"],"contractName":"HorizonStakingExtension","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy","HorizonStakingExtension#ExponentialRebates"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonStakingExtension#HorizonStakingExtension","futureType":"CONTRACT_DEPLOYMENT","libraries":{"ExponentialRebates":"0x5Ab8e4eDb2d068C9c1ab9c96bfb3abCAb96e1534"},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","networkInteraction":{"data":"0x6101e060405234801561001157600080fd5b5060405161396738038061396783398101604081905261003091610411565b818181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610347565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610347565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610347565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610347565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610347565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610347565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610347565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610347565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610347565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b03166101c052506104b4915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038291815260200190565b602060405180830381865afa15801561039f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c39190610444565b9050826001600160a01b0382166103ee5760405163218f5add60e11b81526004016100749190610466565b5092915050565b80516001600160a01b038116811461040c57600080fd5b919050565b6000806040838503121561042457600080fd5b61042d836103f5565b915061043b602084016103f5565b90509250929050565b60006020828403121561045657600080fd5b61045f826103f5565b9392505050565b602081526000825180602084015260005b818110156104945760208186018101516040868401015201610477565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516133d761059060003960008181611c3601528181611e3601526123f00152600061205b015260005050600061178501526000818161213d0152818161280501526129080152600081816112c70152611b6f015260008181610bbf01528181610cbc01528181610ed601526116dc015260005050600050506000505060008181611044015281816111fa01528181612023015281816121b20152818161239a015281816124c2015261263201526133d76000f3fe6080604052600436106101f25760003560e01c806398c657dc1161010d578063b6363cf2116100a0578063e2e1e8e91161006f578063e2e1e8e914610a0b578063e73e14bf14610a38578063f1d60d6614610a70578063fb744cc014610a90578063fc54fb2714610ab057600080fd5b8063b6363cf2146108dd578063b7ca724114610927578063c0641994146109c1578063ccebcabb146109dc57600080fd5b8063a4c0ed36116100dc578063a4c0ed3614610837578063a784d49814610857578063ac9650d814610877578063ae4fe67a146108a457600080fd5b806398c657dc1461072d5780639ce7abe51461075a578063a212daf81461077a578063a2594d821461081757600080fd5b8063561285e411610185578063872d048911610154578063872d04891461064c5780638cc01c861461066c5780638d3c100a146106ed5780639054e3431461070d57600080fd5b8063561285e4146105a95780636a3ca383146105fc5780637573ef4f1461062c5780637a7664601461031157600080fd5b806325d9897e116101c157806325d9897e1461036957806339514ad21461047957806344c32a61146104ab57806355c85269146104cb57600080fd5b806308ce5f68146102495780630e0229231461027c5780631787e69f146103115780631ae720451461034757600080fd5b366102445760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b600080fd5b34801561025557600080fd5b50610269610264366004612bec565b610ac8565b6040519081526020015b60405180910390f35b34801561028857600080fd5b5061029c610297366004612c25565b610add565b604051610273919060006101208201905060018060a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b34801561031d57600080fd5b5061026961032c366004612c25565b6001600160a01b03166000908152600e602052604090205490565b34801561035357600080fd5b50610367610362366004612c25565b610bbd565b005b34801561037557600080fd5b5061046c610384366004612bec565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516102739190612c42565b34801561048557600080fd5b50601a546001600160401b03165b6040516001600160401b039091168152602001610273565b3480156104b757600080fd5b506103676104c6366004612cd2565b610cba565b3480156104d757600080fd5b506105776104e6366004612c25565b6001600160a01b039081166000908152600f602090815260408083208151610120810183528154909516808652600182015493860184905260028201549286018390526003820154606087015260048201546080870152600582015460a0870152600682015460c0870152600782015460e08701819052600890920154610100909601959095529394919390929091565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a001610273565b3480156105b557600080fd5b506105c96105c4366004612bec565b610d68565b60405161027391908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561060857600080fd5b5061061c610617366004612c25565b610df6565b6040519015158152602001610273565b34801561063857600080fd5b50610269610647366004612cfe565b610e1b565b34801561065857600080fd5b50610269610667366004612d4d565b610e7f565b34801561067857600080fd5b506106d2610687366004612c25565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b60408051825181526020928301519281019290925201610273565b3480156106f957600080fd5b50610367610708366004612d96565b610ed4565b34801561071957600080fd5b50610269610728366004612dbb565b6113a0565b34801561073957600080fd5b5061074d610748366004612c25565b611488565b6040516102739190612e11565b34801561076657600080fd5b50610367610775366004612e81565b611493565b34801561078657600080fd5b506105c9610795366004612dbb565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561082357600080fd5b50610367610832366004612c25565b6115be565b34801561084357600080fd5b50610367610852366004612ed5565b6116da565b34801561086357600080fd5b50610269610872366004612c25565b6118e7565b34801561088357600080fd5b50610897610892366004612f30565b6118f2565b6040516102739190612fc9565b3480156108b057600080fd5b5061061c6108bf366004612c25565b6001600160a01b031660009081526022602052604090205460ff1690565b3480156108e957600080fd5b5061061c6108f8366004612bec565b6001600160a01b0380821660009081526015602090815260408083209386168352929052205460ff1692915050565b34801561093357600080fd5b50610996610942366004613049565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b0316908201529181015190820152606001610273565b3480156109cd57600080fd5b50600d5463ffffffff16610493565b3480156109e857600080fd5b506109fc6109f7366004612dbb565b6119d9565b60405190518152602001610273565b348015610a1757600080fd5b50610269610a26366004613049565b60009081526010602052604090205490565b348015610a4457600080fd5b5061061c610a53366004612c25565b6001600160a01b03166000908152600e6020526040902054151590565b348015610a7c57600080fd5b5061061c610a8b366004612c25565b611a2b565b348015610a9c57600080fd5b50610269610aab366004612bec565b611a50565b348015610abc57600080fd5b5060205460ff1661061c565b6000610ad48383611a5c565b90505b92915050565b610b3860405180610120016040528060006001600160a01b0316815260200160008019168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b039081166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e08301526008015461010082015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190613062565b6001600160a01b0316336001600160a01b031614610c7057604051635d9044cd60e01b815260040160405180910390fd5b601880546001600160a01b0319166001600160a01b0383169081179091556040517f690e9b982dc9aefaa1cfed186a2d2045a638013d658104102c9437235bee4b6090600090a250565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c919061307f565b15610d5a57604051632b37d9d160e21b815260040160405180910390fd5b610d648282611a94565b5050565b610d936040518060800160405280600081526020016000815260200160008152602001600081525090565b610dbe6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000610dca8585611e32565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b60006001610e0383611eb6565b6002811115610e1457610e14612dfb565b1492915050565b6001600160a01b038084166000908152601c60209081526040808320938616835292905290812081836002811115610e5557610e55612dfb565b6002811115610e6657610e66612dfb565b81526020019081526020016000205490505b9392505050565b600080610e8c8585611a5c565b90506000610e9a8686611f0f565b90506000610eae63ffffffff8616846130b7565b90506000610ebc8383611f3a565b9050610ec881856130ce565b98975050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061307f565b15610f7457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038116610fb35760405162461bcd60e51b815260206004820152600660248201526521616c6c6f6360d01b604482015260640161023b565b6000610fbe82611eb6565b90506000816002811115610fd457610fd4612dfb565b0361100c5760405162461bcd60e51b81526020600482015260086024820152670858dbdb1b1958dd60c21b604482015260640161023b565b8260000361101957505050565b6001600160a01b0382166000908152600f6020526040812060018101549091859080808061107333867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190611f51565b600d5461108e908690600160401b900463ffffffff1661200e565b935061109a84866130e1565b600d549095506110bb9087908790640100000000900463ffffffff16612047565b92506110c783866130e1565b94508487600501546110d991906130ce565b6005880155600287015460009015806110ff5750601954600160a01b900463ffffffff16155b6111ca5760058801546002890154600d546019546040516349484d8160e01b81526004810194909452602484019290925263ffffffff600160a01b80830482166044860152600160c01b928390048216606486015283048116608485015291041660a4820152735Ab8e4eDb2d068C9c1ab9c96bfb3abCAb96e1534906349484d819060c401602060405180830381865af41580156111a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c591906130f4565b6111cd565b60005b90506111dd81896008015461225a565b92506111e98387611f3a565b92506112296111f884886130e1565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690612274565b82156112915782886008015461123f91906130ce565b60088901558754611259906001600160a01b0316846122bc565b915061126582846130e1565b88546001600160a01b03908116600081815260176020526040902054929550611291928692161561234e565b5086546001600160a01b038a8116918891167ff5ded07502b6feba4c13b19a0c6646efd4b4119f439bcbd49076e4f0ed1eec4b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611323573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134791906130f4565b604080516001600160a01b039093168352602083019190915281018f9052606081018990526080810188905260a081018a905260c0810187905260e081018690526101000160405180910390a450505050505050505050565b6001600160a01b038084166000908152601e60209081526040808320868516845282528083209385168352929052908120600381015482036113e6576000915050610e78565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b801561147c576000818152601d602052604090206001810154426001600160401b039091161161146b5760028301546001840154825461145091906130b7565b61145a919061310d565b61146490856130ce565b9350611471565b5061147c565b600201549050611410565b50909695505050505050565b6000610ad782611eb6565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156114d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f89190613062565b6001600160a01b0316336001600160a01b0316146115585760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611586908690869060040161312f565b600060405180830381600087803b1580156115a057600080fd5b505af11580156115b4573d6000803e3d6000fd5b5050505050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af11580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116239190613062565b6001600160a01b0316336001600160a01b0316146116835760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e0000604482015260640161023b565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156116be57600080fd5b505af11580156116d2573d6000803e3d6000fd5b505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c919061307f565b1561177a57604051632b37d9d160e21b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117e15760405162461bcd60e51b815260206004820152600c60248201526b4f4e4c595f4741544557415960a01b604482015260640161023b565b6018546001600160a01b0385811691161461183e5760405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c315f5354414b494e475f5448524f5547485f4252494447450000604482015260640161023b565b60008061184d838501856131a4565b909250905060ff8216611882576000818060200190518101906118709190613255565b905061187c86826123c4565b506116d2565b60001960ff8316016118b0576000818060200190518101906118a491906132a2565b905061187c86826123d0565b60405162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f434f444560a01b604482015260640161023b565b6000610ad782612740565b604080516000815260208101909152606090826001600160401b0381111561191c5761191c61315e565b60405190808252806020026020018201604052801561194f57816020015b606081526020019060019003908161193a5790505b50915060005b838110156119d1576119ac3086868481811061197357611973613302565b90506020028101906119859190613318565b856040516020016119989392919061335e565b60405160208183030381529060405261278b565b8382815181106119be576119be613302565b6020908102919091010152600101611955565b505092915050565b6040805160208101909152600081526040805160208101909152600081526000611a038686611e32565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b600080611a3783611eb6565b6002811115611a4857611a48612dfb565b141592915050565b6000610ad48383611f0f565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610ad491906130e1565b6000611a9f83611eb6565b90506001816002811115611ab557611ab5612dfb565b14611aec5760405162461bcd60e51b81526020600482015260076024820152662161637469766560c81b604482015260640161023b565b6001600160a01b038381166000908152600f6020908152604091829020825161012081018452815490941684526001810154918401919091526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600801546101008201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663766718086040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef91906130f4565b608082018190526060820151600091611c079161225a565b9050600082600001516001600160a01b0316336001600160a01b03161480611c78575082516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600090815260156020908152604080832093909416825291909152205460ff165b600d54909150600160801b900463ffffffff1682111580611c9b57506040830151155b15611cd55780611cd55760405162461bcd60e51b8152602060048201526005602482015264042c2eae8d60db1b604482015260640161023b565b60808301516001600160a01b0387166000908152600f6020526040908190206004019190915583015115611db957808015611d0f57508415155b15611d2757611d22868460000151612801565b611d36565b611d3483602001516128e7565b505b60408084015184516001600160a01b03166000908152600e6020529190912060010154611d6391906130e1565b83516001600160a01b03166000908152600e602090815260408083206001019390935582860151818701518352601090915291902054611da391906130e1565b6020808501516000908152601090915260409020555b60208084015184516080808701516040808901518151928352958201959095523394810194909452606084018990528415908401526001600160a01b03808a16939116907ff6725dd105a6fc88bb79a6e4627f128577186c567a17c94818d201c2a4ce14039060a00160405180910390a4505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603611e8b57506001600160a01b0382166000908152601460205260409020610ad7565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610ad7565b6001600160a01b038082166000908152600f6020526040812080549192909116611ee35750600092915050565b600381015415801590611ef857506004810154155b15611f065750600192915050565b50600292915050565b600080611f1c8484611e32565b905080600501548160020154611f3291906130e1565b949350505050565b600081831115611f4a5781610ad4565b5090919050565b8015612009576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061307f565b6120095760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b604482015260640161023b565b505050565b60008061201b8484612975565b9050610ad4817f000000000000000000000000000000000000000000000000000000000000000061121a565b60008260000361205957506000610e78565b7f00000000000000000000000000000000000000000000000000000000000000006000831580159061209357506001600160a01b03821615155b90508080156121065750604051634c4ea0ed60e01b8152600481018790526001600160a01b03831690634c4ea0ed90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612106919061307f565b1561224e5760006121178686612975565b90508015612244576040516307470bfb60e21b8152600481018890526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631d1c2fec906024016020604051808303816000875af1158015612186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121aa91906130f4565b506121e283827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906129c7565b60405163102ae65160e31b815260048101889052602481018290526001600160a01b03841690638157328890604401600060405180830381600087803b15801561222b57600080fd5b505af115801561223f573d6000803e3d6000fd5b505050505b9250610e78915050565b50600095945050505050565b600081831161226a576000610ad4565b610ad482846130e1565b8015610d6457604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b1580156116be57600080fd5b6001600160a01b03821660009081526014602052604081206002810154829190158015906122fb57508054600160401b900463ffffffff16620f424010155b156123465780546000906123219063ffffffff600160401b9091048116908790612a0216565b905061232d81866130e1565b925082826002015461233f91906130ce565b6002830155505b509392505050565b8260000361235b57505050565b801561236b576120098284612a69565b6001600160a01b03808316600090815260176020526040902054166123be81156123955781612397565b835b857f00000000000000000000000000000000000000000000000000000000000000006121d2565b50505050565b80516120098184612a69565b80516001600160a01b039081166000908152601b602090815260408083207f0000000000000000000000000000000000000000000000000000000000000000909416835292905290812060030154600160601b90046001600160401b031690036124695760405162461bcd60e51b815260206004820152600a60248201526910b83937bb34b9b4b7b760b11b604482015260640161023b565b80516001600160a01b03908116600090815260146020908152604080832082860151909416835260048401909152902060028201541580156124bb575060038201541515806124bb5750600682015415155b156125b5577f0000000000000000000000000000000000000000000000000000000000000000602084015160405163a9059cbb60e01b81526001600160a01b0391821660048201526024810187905291169063a9059cbb906044016020604051808303816000875af1158015612535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612559919061307f565b5082602001516001600160a01b031683600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de866040516125a791815260200190565b60405180910390a350505050565b60008260020154600014806125d1575082600501548360020154145b61260757826005015483600201546125e991906130e1565b60038401546125f890876130b7565b612602919061310d565b612609565b845b905080158061261f5750670de0b6b3a764000085105b156126ae576126548460200151866121d27f000000000000000000000000000000000000000000000000000000000000000090565b83602001516001600160a01b031684600001516001600160a01b03167f0921ebf1ba63d93aed0e18402fa38cb5515048daf6a04549c1bd1c1f560d72de876040516126a191815260200190565b60405180910390a3612739565b8483600201546126be91906130ce565b600284015560038301546126d39082906130ce565b600384015581546126e59082906130ce565b82556020808501518551604080518981529384018590526001600160a01b039283169391909216917fcd0366dce5247d874ffc60a762aa7abbb82c1695bbb171609c1b8861e279eb73910160405180910390a35b5050505050565b6001600160a01b0381166000908152600e6020526040812060028101546001820154600483015492549192909161277791906130e1565b61278191906130e1565b610ad791906130e1565b6060600080846001600160a01b0316846040516127a89190613385565b600060405180830381855af49150503d80600081146127e3576040519150601f19603f3d011682016040523d82523d6000602084013e6127e8565b606091505b50915091506127f8858383612ae8565b95945050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000604051636dba849360e11b81526001600160a01b038581166004830152919091169063db750926906024016020604051808303816000875af115801561286e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289291906130f4565b9050806000036128a157505050565b60006128ad8383612b44565b905060006128bb82846130e1565b6001600160a01b038086166000908152601760205260409020549192506127399183918791161561234e565b6040516377561f0760e11b8152600481018290526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063eeac3e0e906024016020604051808303816000875af1158015612951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad791906130f4565b600061298482620f4240101590565b82906129a657604051633dc311df60e01b815260040161023b91815260200190565b506129bd6129b783620f42406130e1565b84612a02565b610ad490846130e1565b80156120095760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401611f8e565b6000612a1183620f4240101590565b80612a245750612a2482620f4240101590565b83839091612a4e5760405163768bf0eb60e11b81526004810192909252602482015260440161023b565b50620f42409050612a5f83856130b7565b610ad4919061310d565b6001600160a01b0382166000908152600e6020526040902054612a8d9082906130ce565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290612adc9084815260200190565b60405180910390a25050565b606082612afd57612af882612bab565b610e78565b8151158015612b1457506001600160a01b0384163b155b15612b3d57604051639996b31560e01b81526001600160a01b038516600482015260240161023b565b5080610e78565b6001600160a01b0382166000908152601460205260408120600281015482919015801590612b8457508054640100000000900463ffffffff16620f424010155b156123465780546000906123219063ffffffff6401000000009091048116908790612a0216565b805115612bbb5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114612bd457600080fd5b60008060408385031215612bff57600080fd5b8235612c0a81612bd7565b91506020830135612c1a81612bd7565b809150509250929050565b600060208284031215612c3757600080fd5b8135610ad481612bd7565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151612cb060c084018263ffffffff169052565b5060e0830151612ccb60e08401826001600160401b03169052565b5092915050565b60008060408385031215612ce557600080fd5b8235612cf081612bd7565b946020939093013593505050565b600080600060608486031215612d1357600080fd5b8335612d1e81612bd7565b92506020840135612d2e81612bd7565b9150604084013560038110612d4257600080fd5b809150509250925092565b600080600060608486031215612d6257600080fd5b8335612d6d81612bd7565b92506020840135612d7d81612bd7565b9150604084013563ffffffff81168114612d4257600080fd5b60008060408385031215612da957600080fd5b823591506020830135612c1a81612bd7565b600080600060608486031215612dd057600080fd5b8335612ddb81612bd7565b92506020840135612deb81612bd7565b91506040840135612d4281612bd7565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612e3357634e487b7160e01b600052602160045260246000fd5b91905290565b60008083601f840112612e4b57600080fd5b5081356001600160401b03811115612e6257600080fd5b602083019150836020828501011115612e7a57600080fd5b9250929050565b600080600060408486031215612e9657600080fd5b8335612ea181612bd7565b925060208401356001600160401b03811115612ebc57600080fd5b612ec886828701612e39565b9497909650939450505050565b60008060008060608587031215612eeb57600080fd5b8435612ef681612bd7565b93506020850135925060408501356001600160401b03811115612f1857600080fd5b612f2487828801612e39565b95989497509550505050565b60008060208385031215612f4357600080fd5b82356001600160401b03811115612f5957600080fd5b8301601f81018513612f6a57600080fd5b80356001600160401b03811115612f8057600080fd5b8560208260051b8401011115612f9557600080fd5b6020919091019590945092505050565b60005b83811015612fc0578181015183820152602001612fa8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561303d57603f198786030184528151805180875261301a816020890160208501612fa5565b601f01601f19169590950160209081019550938401939190910190600101612ff1565b50929695505050505050565b60006020828403121561305b57600080fd5b5035919050565b60006020828403121561307457600080fd5b8151610ad481612bd7565b60006020828403121561309157600080fd5b81518015158114610ad457600080fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610ad757610ad76130a1565b80820180821115610ad757610ad76130a1565b81810381811115610ad757610ad76130a1565b60006020828403121561310657600080fd5b5051919050565b60008261312a57634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561319c5761319c61315e565b604052919050565b600080604083850312156131b757600080fd5b823560ff811681146131c857600080fd5b915060208301356001600160401b038111156131e357600080fd5b8301601f810185136131f457600080fd5b80356001600160401b0381111561320d5761320d61315e565b613220601f8201601f1916602001613174565b81815286602083850101111561323557600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000602082840312801561326857600080fd5b50604051602081016001600160401b038111828210171561328b5761328b61315e565b604052825161329981612bd7565b81529392505050565b600060408284031280156132b557600080fd5b50604080519081016001600160401b03811182821017156132d8576132d861315e565b60405282516132e681612bd7565b815260208301516132f681612bd7565b60208201529392505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261332f57600080fd5b8301803591506001600160401b0382111561334957600080fd5b602001915036819003821315612e7a57600080fd5b82848237600083820160008152835161337b818360208801612fa5565b0195945050505050565b60008251613397818460208701612fa5565b919091019291505056fea264697066735822122038ad83d20c219353421029f1ad8c4f7667d5f0e86af1579c64603bb56827d86064736f6c634300081b00330000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca0000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","networkInteractionId":1,"nonce":591,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xdc3e61147eae510ca156b998d535ab74b7b47007e313416d6b17a88048f1f51f"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","hash":"0xdc3e61147eae510ca156b998d535ab74b7b47007e313416d6b17a88048f1f51f","networkInteractionId":1,"receipt":{"blockHash":"0x5d0f2b163e68c20fa939b3e9f4e15938d06b356a60c7ff1c52692fa839b9206b","blockNumber":82178120,"contractAddress":"0xf203161Ba7e25263deB79a4478BE18644C2c5446","logs":[{"address":"0xf203161Ba7e25263deB79a4478BE18644C2c5446","data":"0x000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f0000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea74906340000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f11000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da0000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860","logIndex":0,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x0000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd340702","0x0000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStakingExtension#HorizonStakingExtension","result":{"address":"0xf203161Ba7e25263deB79a4478BE18644C2c5446","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"PaymentsEscrow#PaymentsEscrow","constructorArgs":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa",10000,10000],"contractName":"PaymentsEscrow","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"PaymentsEscrow#PaymentsEscrow","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"PaymentsEscrow#PaymentsEscrow","networkInteraction":{"data":"0x61020060405234801561001157600080fd5b506040516120c73803806120c78339810160408190526100309161046b565b826001600160a01b03811661007a5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b2906103a1565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e5906103a1565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261011e906103a1565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b6020820152610158906103a1565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b6020820152610190906103a1565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101cb906103a1565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b6020820152610209906103a1565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b6020820152610245906103a1565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027a906103a1565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103249790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450816276a7008082111561035c57604051635c0f65a160e01b815260048101929092526024820152604401610071565b508190506276a7008082111561038e57604051635c0f65a160e01b815260048101929092526024820152604401610071565b50506101c0919091526101e05250610510565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b81526004016103dc91815260200190565b602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d91906104a0565b9050826001600160a01b0382166104485760405163218f5add60e11b815260040161007191906104c2565b5092915050565b80516001600160a01b038116811461046657600080fd5b919050565b60008060006060848603121561048057600080fd5b6104898461044f565b602085015160409095015190969495509392505050565b6000602082840312156104b257600080fd5b6104bb8261044f565b9392505050565b602081526000825180602084015260005b818110156104f057602081860181015160408684010152016104d3565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051611ad26105f5600039600081816101e00152610abb015260008181610193015261039d01526000505060005050600050506000505060005050600081816102fa0152818161041601528181610589015281816106380152818161076e0152818161094901528181610b2d01528181610d71015261131b01526000505060008181610fa6015261104e015260005050600081816108da01528181610eea01528181610f77015281816110c401526114130152611ad26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806378a24c54116100a257806388e584431161007157806388e584431461021d578063ac9650d81461026e578063beb6eceb1461028e578063d4fac45d146102d2578063f213159c146102e557600080fd5b806378a24c54146101c85780637b8ae6cf146101db5780638129fc1c1461020257806387dbfe821461020a57600080fd5b80634f9d392e116100de5780634f9d392e1461016857806351cff8d91461017b5780636cd476561461018e57806371ece3aa146101b557600080fd5b8063071b214c146101105780630ee36be31461012d57806332825b811461014257806347e7ef2414610155575b600080fd5b61011a6276a70081565b6040519081526020015b60405180910390f35b61014061013b3660046116df565b6102f8565b005b6101406101503660046116df565b610414565b6101406101633660046116fa565b610587565b6101406101763660046116fa565b610636565b6101406101893660046116df565b61076c565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b6101406101c33660046116fa565b610947565b6101406101d63660046116df565b610b2b565b61011a7f000000000000000000000000000000000000000000000000000000000000000081565b610140610c61565b610140610218366004611724565b610d6f565b61025361022b366004611792565b6001602081815260009384526040808520909152918352912080549181015460029091015483565b60408051938452602084019290925290820152606001610124565b61028161027c3660046117c5565b6111ee565b6040516101249190611860565b6102bd61029c366004611792565b60006020818152928152604080822090935290815220805460019091015482565b60408051928352602083019190915201610124565b61011a6102e0366004611792565b6112d7565b6101406102f33660046118e0565b611319565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037a919061191d565b1561039857604051639e68cf0b60e01b815260040160405180910390fd5b6103c27f000000000000000000000000000000000000000000000000000000000000000042611955565b336000818152602081815260408083206001600160a01b03871680855292528083206001019490945592517f47c16ea40fc834cf4be3dc9ec160a1ff77ba18b1231e9e6886e3231c708326ff9190a350565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610496919061191d565b156104b457604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0385168452909152812060018101549091036104fa57604051638cbd172f60e01b815260040160405180910390fd5b6001810154429081811061052f57604051633c50db7960e11b8152600481019290925260248201526044015b60405180910390fd5b5050336000818152602081815260408083206001600160a01b0387168085529252808320838155600101839055519092917f3d7c3b7414bb2ce0675b85ea842ee937d10fe3b291f1cb2dc3361510bd113d9091a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610609919061191d565b1561062757604051639e68cf0b60e01b815260040160405180910390fd5b6106323383836113c9565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b8919061191d565b156106d657604051639e68cf0b60e01b815260040160405180910390fd5b806000036106f757604051633aff1f3760e21b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b0386168452909152812080549091839183919061072c908490611955565b90915550506040516001600160a01b0384169033907f747c06b7cbf7a0f7fcab1fdf4f7429ac2afcdf5f0af97b9ef717110eef00eb9990600090a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee919061191d565b1561080c57604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b03851684529091528120600281015490910361085457604051638cbd172f60e01b815260040160405180910390fd5b6002810154429081811061088457604051633c50db7960e11b815260048101929092526024820152604401610526565b5050600081600001548260010154116108a15781600101546108a4565b81545b9050808260000160008282546108ba9190611968565b909155505060006001830181905560028301556109016001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338361147f565b6040518181526001600160a01b0384169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb906020015b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061191d565b156109e757604051639e68cf0b60e01b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812090829003610a80578060010154600003610a3757604051638cbd172f60e01b815260040160405180910390fd5b600060018201819055600282018190556040516001600160a01b0385169133917fb2486c13d5da6cdbddffe9f9ec53350f7f15033cec803877fd75ff89d734c9489190a3505050565b80548280821015610aad57604051633db4e69160e01b815260048101929092526024820152604401610526565b505060018101829055610ae07f000000000000000000000000000000000000000000000000000000000000000042611955565b600282018190556040805184815260208101929092526001600160a01b0385169133917fe0158cfeff9c2315fdbefe5851ad77d36eb492293f2b6b3861a73fb4dff82451910161093a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bad919061191d565b15610bcb57604051639e68cf0b60e01b815260040160405180910390fd5b336000908152602081815260408083206001600160a01b03851684529091528120600101549003610c0f57604051638cbd172f60e01b815260040160405180910390fd5b336000818152602081815260408083206001600160a01b0386168085529252808320600101839055519092917f988de7a3afe0d801be198872279c1fd9771d8013712ee4f00652354c8a6ec27d91a350565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015610ca75750825b905060008267ffffffffffffffff166001148015610cc45750303b155b905081158015610cd2575080155b15610cf05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d1a57845460ff60401b1916600160401b1785555b610d22611531565b8315610d6857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df1919061191d565b15610e0f57604051639e68cf0b60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320338452909152902080548480821015610e5d5760405163b0b503e760e01b815260048101929092526024820152604401610526565b50506001600160a01b03808716600090815260016020908152604080832093891683529290522080548580821015610eb157604051633db4e69160e01b815260048101929092526024820152604401610526565b505084826000016000828254610ec79190611968565b9091555050805485908290600090610ee0908490611968565b90915550600090507f00000000000000000000000000000000000000000000000000000000000000006040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f73919061197b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018990526044016020604051808303816000875af1158015611012573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611036919061191d565b50604051633634bc1d60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636c69783a9061108b908c908b908b908b908b90600401611994565b600060405180830381600087803b1580156110a557600080fd5b505af11580156110b9573d6000803e3d6000fd5b5050505060006110e67f000000000000000000000000000000000000000000000000000000000000000090565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611150919061197b565b905061115c8188611955565b821482828990919261119257604051631f82726b60e21b8152600481019390935260248301919091526044820152606401610526565b505050876001600160a01b0316896001600160a01b03167f8b0d8feeba4c6c21a8b1c772ccc0ec89892541c94a76b356c6a1035ec8f5b40d896040516111da91815260200190565b60405180910390a350505050505050505050565b6040805160008152602081019091526060908267ffffffffffffffff811115611219576112196119df565b60405190808252806020026020018201604052801561124c57816020015b60608152602001906001900390816112375790505b50915060005b838110156112ce576112a930868684818110611270576112706119f5565b90506020028101906112829190611a0b565b8560405160200161129593929190611a59565b60405160208183030381529060405261153b565b8382815181106112bb576112bb6119f5565b6020908102919091010152600101611252565b50505b92915050565b6001600160a01b03808316600090815260016020818152604080842094861684529390529181209182015482549192916113119190611968565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b919061191d565b156113b957604051639e68cf0b60e01b815260040160405180910390fd5b6113c48383836113c9565b505050565b6001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290611400908490611955565b9091555061143a90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836115b1565b816001600160a01b0316836001600160a01b03167f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f628360405161093a91815260200190565b80156113c45760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044015b6020604051808303816000875af11580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f9919061191d565b6113c45760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b6044820152606401610526565b6115396115f2565b565b6060600080846001600160a01b0316846040516115589190611a80565b600060405180830381855af49150503d8060008114611593576040519150601f19603f3d011682016040523d82523d6000602084013e611598565b606091505b50915091506115a885838361163b565b95945050505050565b80156113c4576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064016114b6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661153957604051631afcd79f60e31b815260040160405180910390fd5b6060826116505761164b8261169a565b611693565b815115801561166757506001600160a01b0384163b155b1561169057604051639996b31560e01b81526001600160a01b0385166004820152602401610526565b50805b9392505050565b8051156116aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146116da57600080fd5b919050565b6000602082840312156116f157600080fd5b611693826116c3565b6000806040838503121561170d57600080fd5b611716836116c3565b946020939093013593505050565b60008060008060008060c0878903121561173d57600080fd5b86356003811061174c57600080fd5b955061175a602088016116c3565b9450611768604088016116c3565b93506060870135925061177d608088016116c3565b9598949750929591949360a090920135925050565b600080604083850312156117a557600080fd5b6117ae836116c3565b91506117bc602084016116c3565b90509250929050565b600080602083850312156117d857600080fd5b823567ffffffffffffffff8111156117ef57600080fd5b8301601f8101851361180057600080fd5b803567ffffffffffffffff81111561181757600080fd5b8560208260051b840101111561182c57600080fd5b6020919091019590945092505050565b60005b8381101561185757818101518382015260200161183f565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156118d457603f19878603018452815180518087526118b181602089016020850161183c565b601f01601f19169590950160209081019550938401939190910190600101611888565b50929695505050505050565b6000806000606084860312156118f557600080fd5b6118fe846116c3565b925061190c602085016116c3565b929592945050506040919091013590565b60006020828403121561192f57600080fd5b8151801515811461169357600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156112d1576112d161193f565b818103818111156112d1576112d161193f565b60006020828403121561198d57600080fd5b5051919050565b60a08101600387106119b657634e487b7160e01b600052602160045260246000fd5b9581526001600160a01b0394851660208201526040810193909352921660608201526080015290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611a2257600080fd5b83018035915067ffffffffffffffff821115611a3d57600080fd5b602001915036819003821315611a5257600080fd5b9250929050565b828482376000838201600081528351611a7681836020880161183c565b0195945050505050565b60008251611a9281846020870161183c565b919091019291505056fea2646970667358221220c747a690c4d61350849293110a4c3ac2070e62afe88696f58021adec428f19e564736f6c634300081b00330000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca00000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002710","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"PaymentsEscrow#PaymentsEscrow","networkInteractionId":1,"nonce":592,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x51d4e4c47fba62927e62668113a50c544749571902b2aff50096816224ec219b"},"type":"TRANSACTION_SEND"} +{"futureId":"PaymentsEscrow#PaymentsEscrow","hash":"0x51d4e4c47fba62927e62668113a50c544749571902b2aff50096816224ec219b","networkInteractionId":1,"receipt":{"blockHash":"0x6127edf707f7a533633004ad6ee427c65b06b5e5460f588388e56a540fe758b5","blockNumber":82178135,"contractAddress":"0x09B985a2042848A08bA59060EaF0f07c6F5D4d54","logs":[{"address":"0x09B985a2042848A08bA59060EaF0f07c6F5D4d54","data":"0x000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f0000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea74906340000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f11000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da0000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860","logIndex":0,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x0000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd340702","0x0000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"PaymentsEscrow#PaymentsEscrow","result":{"address":"0x09B985a2042848A08bA59060EaF0f07c6F5D4d54","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"artifactId":"PaymentsEscrow#PaymentsEscrow_Instance","contractAddress":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","contractName":"PaymentsEscrow","dependencies":["HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow"],"futureId":"PaymentsEscrow#PaymentsEscrow_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"TAPCollector#TAPCollector","constructorArgs":["TAPCollector","1","0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa"],"contractName":"TAPCollector","dependencies":["Controller#Controller","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"TAPCollector#TAPCollector","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"TAPCollector#TAPCollector","networkInteraction":{"data":"0x6102a060405234801561001157600080fd5b506040516119ae3803806119ae833981016040819052610030916105d9565b80838361003e8260006103db565b6101205261004d8160016103db565b61014052815160208084019190912060e052815190820120610100524660a0526100da60e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c0526001600160a01b03811661012c5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101e05260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526101649061040e565b6001600160a01b0316610160526040805180820190915260078152665374616b696e6760c81b60208201526101989061040e565b6001600160a01b03166101805260408051808201909152600d81526c47726170685061796d656e747360981b60208201526101d29061040e565b6001600160a01b03166101a05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261020d9061040e565b6001600160a01b03166101c05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b60208201526102469061040e565b6001600160a01b03166102005260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526102819061040e565b6001600160a01b0316610220526040805180820190915260118152704772617068546f6b656e4761746577617960781b60208201526102bf9061040e565b6001600160a01b03166102405260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b60208201526102fb9061040e565b6001600160a01b03166102605260408051808201909152600881526721bab930ba34b7b760c11b60208201526103309061040e565b6001600160a01b039081166102808190526101e05161018051610160516101a0516101c0516102005161022051610240516102605160408051968c168752948b166020870152928a1685850152908916606085015288166080840152871660a083015260c0820195909552935192851694918216939116917fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a439181900360e00190a45050505061081e565b60006020835110156103f7576103f0836104bc565b9050610408565b8161040284826106db565b5060ff90505b92915050565b6000806101e0516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161044991815260200190565b602060405180830381865afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a9190610799565b9050826001600160a01b0382166104b55760405163218f5add60e11b815260040161012391906107e7565b5092915050565b600080829050601f815111156104e7578260405163305a27a960e01b815260040161012391906107e7565b80516104f2826107fa565b179392505050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561052b578181015183820152602001610513565b50506000910152565b600082601f83011261054557600080fd5b81516001600160401b0381111561055e5761055e6104fa565b604051601f8201601f19908116603f011681016001600160401b038111828210171561058c5761058c6104fa565b6040528181528382016020018510156105a457600080fd5b6105b5826020830160208701610510565b949350505050565b80516001600160a01b03811681146105d457600080fd5b919050565b6000806000606084860312156105ee57600080fd5b83516001600160401b0381111561060457600080fd5b61061086828701610534565b602086015190945090506001600160401b0381111561062e57600080fd5b61063a86828701610534565b925050610649604085016105bd565b90509250925092565b600181811c9082168061066657607f821691505b60208210810361068657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156106d657806000526020600020601f840160051c810160208510156106b35750805b601f840160051c820191505b818110156106d357600081556001016106bf565b50505b505050565b81516001600160401b038111156106f4576106f46104fa565b610708816107028454610652565b8461068c565b6020601f82116001811461073c57600083156107245750848201515b600019600385901b1c1916600184901b1784556106d3565b600084815260208120601f198516915b8281101561076c578785015182556020948501946001909201910161074c565b508482101561078a5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6000602082840312156107ab57600080fd5b6107b4826105bd565b9392505050565b600081518084526107d3816020860160208601610510565b601f01601f19169290920160200192915050565b6020815260006107b460208301846107bb565b805160208083015191908110156106865760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516110e36108cb600039600050506000505060005050600050506000505060005050600061024f0152600050506000505060005050600061049201526000610460015260006108940152600061086c015260006107c7015260006107f10152600061081b01526110e36000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631ef518f21461005c5780637f07d2831461008c57806384b0196e146100ad5780638821603c146100c8578063cfdb35bd146100db575b600080fd5b61006f61006a3660046109dc565b61010c565b6040516001600160a01b0390911681526020015b60405180910390f35b61009f61009a366004610b23565b610125565b604051908152602001610083565b6100b5610372565b6040516100839796959493929190610bc6565b61009f6100d6366004610c5e565b6103b8565b61009f6100e9366004610cb0565b600260209081526000938452604080852082529284528284209052825290205481565b600061011f61011a83610db8565b6103cb565b92915050565b60008060008380602001905181019061013e9190610e75565b815151919350915033906001600160a01b0381168214610189576040516347666ba360e11b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b50508151516000610199846103cb565b84516020808201516060909201516001600160a01b038087166000908152600284526040808220838716835285528082209287168252919093529091205492935090916001600160801b03909116908181808211610213576040516308e467d960e31b815260048101929092526024820152604401610180565b50600090506102228284610fb1565b9050600061023082896103f2565b905081156102f3576040516343edff4160e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906387dbfe829061028e908f908a908a9088908e908990600401610fda565b600060405180830381600087803b1580156102a857600080fd5b505af11580156102bc573d6000803e3d6000fd5b5050506001600160a01b0380891660009081526002602090815260408083208a851684528252808320938b16835292905220859055505b866001600160a01b0316866001600160a01b03168d600281111561031957610319610fc4565b604080516001600160a01b038a168152602081018790529081018590527ffadd34108e3c00b000a046b272ee080bb1755b91078c0ef5200c0b7da6132bd19060600160405180910390a4509a9950505050505050505050565b600060608060008060006060610386610459565b61038e61048b565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b600061011f6103c68361102e565b6104b8565b6000806103db83600001516104b8565b90506103eb81846020015161056f565b9392505050565b600061040183620f4240101590565b80610414575061041482620f4240101590565b8383909161043e5760405163768bf0eb60e11b815260048101929092526024820152604401610180565b50620f4240905061044f838561103a565b6103eb9190611051565b60606104867f00000000000000000000000000000000000000000000000000000000000000006000610599565b905090565b60606104867f00000000000000000000000000000000000000000000000000000000000000006001610599565b600061011f7fe502a96d6aaed328ceacc76a5f627b9823162f5a205dab5a702b40073a6778428360000151846020015185604001518660600151876080015180519060200120604051602001610554969594939291909586526001600160a01b0394851660208701529290931660408501526001600160401b031660608401526001600160801b0391909116608083015260a082015260c00190565b60405160208183030381529060405280519060200120610644565b60008060008061057f8686610671565b92509250925061058f82826106be565b5090949350505050565b606060ff83146105b3576105ac8361077b565b905061011f565b8180546105bf90611073565b80601f01602080910402602001604051908101604052809291908181526020018280546105eb90611073565b80156106385780601f1061060d57610100808354040283529160200191610638565b820191906000526020600020905b81548152906001019060200180831161061b57829003601f168201915b5050505050905061011f565b600061011f6106516107ba565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600083516041036106ab5760208401516040850151606086015160001a61069d888285856108e5565b9550955095505050506106b7565b50508151600091506002905b9250925092565b60008260038111156106d2576106d2610fc4565b036106db575050565b60018260038111156106ef576106ef610fc4565b0361070d5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561072157610721610fc4565b036107425760405163fce698f760e01b815260048101829052602401610180565b600382600381111561075657610756610fc4565b03610777576040516335e2f38360e21b815260048101829052602401610180565b5050565b60606000610788836109b4565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561081357507f000000000000000000000000000000000000000000000000000000000000000046145b1561083d57507f000000000000000000000000000000000000000000000000000000000000000090565b610486604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561092057506000915060039050826109aa565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610974573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109a0575060009250600191508290506109aa565b9250600091508190505b9450945094915050565b600060ff8216601f81111561011f57604051632cd44ac360e21b815260040160405180910390fd5b6000602082840312156109ee57600080fd5b81356001600160401b03811115610a0457600080fd5b8201604081850312156103eb57600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715610a4e57610a4e610a16565b60405290565b604080519081016001600160401b0381118282101715610a4e57610a4e610a16565b604051601f8201601f191681016001600160401b0381118282101715610a9e57610a9e610a16565b604052919050565b60006001600160401b03821115610abf57610abf610a16565b50601f01601f191660200190565b600082601f830112610ade57600080fd5b8135610af1610aec82610aa6565b610a76565b818152846020838601011115610b0657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215610b3657600080fd5b823560038110610b4557600080fd5b915060208301356001600160401b03811115610b6057600080fd5b610b6c85828601610acd565b9150509250929050565b60005b83811015610b91578181015183820152602001610b79565b50506000910152565b60008151808452610bb2816020860160208601610b76565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e060208201526000610be560e0830189610b9a565b8281036040840152610bf78189610b9a565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b81811015610c4d578351835260209384019390920191600101610c2f565b50909b9a5050505050505050505050565b600060208284031215610c7057600080fd5b81356001600160401b03811115610c8657600080fd5b820160a081850312156103eb57600080fd5b6001600160a01b0381168114610cad57600080fd5b50565b600080600060608486031215610cc557600080fd5b8335610cd081610c98565b92506020840135610ce081610c98565b91506040840135610cf081610c98565b809150509250925092565b6001600160401b0381168114610cad57600080fd5b6001600160801b0381168114610cad57600080fd5b600060a08284031215610d3757600080fd5b610d3f610a2c565b90508135610d4c81610c98565b81526020820135610d5c81610c98565b60208201526040820135610d6f81610cfb565b60408201526060820135610d8281610d10565b606082015260808201356001600160401b03811115610da057600080fd5b610dac84828501610acd565b60808301525092915050565b600060408236031215610dca57600080fd5b610dd2610a54565b82356001600160401b03811115610de857600080fd5b610df436828601610d25565b82525060208301356001600160401b03811115610e1057600080fd5b610e1c36828601610acd565b60208301525092915050565b600082601f830112610e3957600080fd5b8151610e47610aec82610aa6565b818152846020838601011115610e5c57600080fd5b610e6d826020830160208701610b76565b949350505050565b60008060408385031215610e8857600080fd5b82516001600160401b03811115610e9e57600080fd5b830160408186031215610eb057600080fd5b610eb8610a54565b81516001600160401b03811115610ece57600080fd5b820160a08188031215610ee057600080fd5b610ee8610a2c565b8151610ef381610c98565b81526020820151610f0381610c98565b60208201526040820151610f1681610cfb565b60408201526060820151610f2981610d10565b606082015260808201516001600160401b03811115610f4757600080fd5b610f5389828501610e28565b60808301525082525060208201516001600160401b03811115610f7557600080fd5b610f8187828501610e28565b602083810191909152959095015190969095509350505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011f5761011f610f9b565b634e487b7160e01b600052602160045260246000fd5b60c0810160038810610ffc57634e487b7160e01b600052602160045260246000fd5b9681526001600160a01b03958616602082015293851660408501526060840192909252909216608082015260a0015290565b600061011f3683610d25565b808202811582820484141761011f5761011f610f9b565b60008261106e57634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061108757607f821691505b6020821081036110a757634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212204ea11b7f590e7303a0b1850b4cd59148c357bb48498bdb2606c6e97c057012e264736f6c634300081b0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000000000000000000000000000000000000000000c544150436f6c6c6563746f72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"TAPCollector#TAPCollector","networkInteractionId":1,"nonce":593,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xea63076f31f70c31ffd7c170d6d50962f7f5f465c5e556d221e4de6dbdc8175e"},"type":"TRANSACTION_SEND"} +{"futureId":"TAPCollector#TAPCollector","hash":"0xea63076f31f70c31ffd7c170d6d50962f7f5f465c5e556d221e4de6dbdc8175e","networkInteractionId":1,"receipt":{"blockHash":"0x683c27716ab788fe88104bd8ab560e75e6279df88f2ce4cd4072769e69bde2b1","blockNumber":82178150,"contractAddress":"0xacC71844EF6beEF70106ABe6E51013189A1f3738","logs":[{"address":"0xacC71844EF6beEF70106ABe6E51013189A1f3738","data":"0x000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f0000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea74906340000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f11000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da0000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860","logIndex":0,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x0000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd340702","0x0000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"TAPCollector#TAPCollector","result":{"address":"0xacC71844EF6beEF70106ABe6E51013189A1f3738","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":[],"artifactId":"GraphPayments#GraphPayments","dependencies":["GraphPayments#GraphPayments"],"functionName":"initialize","futureId":"GraphPayments#encodeFunctionCall(GraphPayments#GraphPayments.initialize)","result":"0x8129fc1c","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"artifactId":"HorizonStaking#HorizonStaking","constructorArgs":["0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","0xf203161Ba7e25263deB79a4478BE18644C2c5446","0x0000000000000000000000000000000000000000"],"contractName":"HorizonStaking","dependencies":["Controller#Controller","HorizonStakingExtension#HorizonStakingExtension","GraphHorizon_Periphery#Dummy","HorizonProxies#RegisteredDummy"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","futureId":"HorizonStaking#HorizonStaking","futureType":"CONTRACT_DEPLOYMENT","libraries":{},"strategy":"basic","strategyConfig":{},"type":"DEPLOYMENT_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStaking#HorizonStaking","networkInteraction":{"data":"0x61020060405234801561001157600080fd5b50604051615b2c380380615b2c8339810160408190526100309161041b565b828181806001600160a01b03811661007d5760405163218f5add60e11b815260206004820152600a60248201526921b7b73a3937b63632b960b11b60448201526064015b60405180910390fd5b6001600160a01b0381166101005260408051808201909152600a81526923b930b8342a37b5b2b760b11b60208201526100b590610351565b6001600160a01b03166080526040805180820190915260078152665374616b696e6760c81b60208201526100e890610351565b6001600160a01b031660a05260408051808201909152600d81526c47726170685061796d656e747360981b602082015261012190610351565b6001600160a01b031660c05260408051808201909152600e81526d5061796d656e7473457363726f7760901b602082015261015b90610351565b6001600160a01b031660e05260408051808201909152600c81526b22b837b1b426b0b730b3b2b960a11b602082015261019390610351565b6001600160a01b03166101205260408051808201909152600e81526d2932bbb0b93239a6b0b730b3b2b960911b60208201526101ce90610351565b6001600160a01b0316610140526040805180820190915260118152704772617068546f6b656e4761746577617960781b602082015261020c90610351565b6001600160a01b03166101605260408051808201909152600f81526e23b930b834283937bc3ca0b236b4b760891b602082015261024890610351565b6001600160a01b03166101805260408051808201909152600881526721bab930ba34b7b760c11b602082015261027d90610351565b6001600160a01b039081166101a08190526101005160a05160805160c05160e05161012051610140516101605161018051604051988b169a9788169996909716977fef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43976103279790916001600160a01b03978816815295871660208701529386166040860152918516606085015284166080840152831660a083015290911660c082015260e00190565b60405180910390a450506001600160a01b039081166101c052929092166101e052506104ce915050565b600080610100516001600160a01b031663f7641a5e84805190602001206040518263ffffffff1660e01b815260040161038c91815260200190565b602060405180830381865afa1580156103a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cd919061045e565b9050826001600160a01b0382166103f85760405163218f5add60e11b81526004016100749190610480565b5092915050565b80516001600160a01b038116811461041657600080fd5b919050565b60008060006060848603121561043057600080fd5b610439846103ff565b9250610447602085016103ff565b9150610455604085016103ff565b90509250925092565b60006020828403121561047057600080fd5b610479826103ff565b9392505050565b602081526000825180602084015260005b818110156104ae5760208186018101516040868401015201610491565b506000604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516155836105a960003960006102fb015260008181610dbf015281816115b60152818161166801528181612f5401528181613e120152614172015260005050600050506000505060005050600050506000612f0d015260005050600050506000505060008181610d89015281816117cd015281816125b2015281816128c80152818161295f01528181612ac00152818161380b015281816139cb01528181613d88015261401e01526155836000f3fe6080604052600436106102975760003560e01c80638cc01c861161015a578063b7ca7241116100c1578063ee6a17441161007a578063ee6a174414610b5a578063ef58bd6714610b7a578063f93f1cd014610b8f578063fb744cc014610baf578063fc54fb2714610bcf578063fecc9cc114610be7576102e9565b8063b7ca724114610a1c578063bc735d9014610ab6578063ca94b0e914610ad6578063ccebcabb14610af6578063e473522a14610b25578063e76fede614610b3a576102e9565b8063a2a3172211610113578063a2a3172214610936578063a694fc3a14610956578063a784d49814610976578063ac9650d814610996578063ad4d35b5146109c3578063ae4fe67a146109e3576102e9565b80638cc01c86146107985780639054e343146108195780639ce7abe514610839578063a02b942614610859578063a212daf814610879578063a2594d8214610916576102e9565b80634d99dd16116101fe5780637573ef4f116101b75780637573ef4f146106b25780637a766460146106d25780637c145cc71461070857806381e21b561461073857806382d66cb814610758578063872d048914610778576102e9565b80634d99dd16146105bf57806351a60b02146105df578063561285e4146105ff5780636230001a1461065257806372f2c2b5146106725780637461209214610692576102e9565b80632e17de78116102505780632e17de781461050257806339514ad2146105225780633a78b7321461054a5780633ccfd60b1461056a57806342c516931461057f5780634ca7ac221461059f576102e9565b8063010167e51461033f578063026e402b1461035f57806308ce5f681461037f57806321195373146103b2578063259bc435146103d257806325d9897e146103f2576102e9565b366102e95760405162461bcd60e51b815260206004820152601760248201527f524543454956455f4554485f4e4f545f414c4c4f57454400000000000000000060448201526064015b60405180910390fd5b3480156102f557600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000009036600082376000803683855af43d806000843e818015610339578184f35b8184fd5b005b34801561034b57600080fd5b5061033d61035a366004614caf565b610c07565b34801561036b57600080fd5b5061033d61037a366004614d11565b610cda565b34801561038b57600080fd5b5061039f61039a366004614d3d565b610dea565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b5061033d6103cd366004614d76565b610dff565b3480156103de57600080fd5b5061033d6103ed366004614db7565b610ece565b3480156103fe57600080fd5b506104f561040d366004614d3d565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152506001600160a01b039182166000908152601b602090815260408083209390941682529182528290208251610100810184528154815260018201549281019290925260028101549282019290925260039091015463ffffffff808216606084015264010000000082046001600160401b039081166080850152600160601b8304811660a0850152600160a01b830490911660c0840152600160c01b9091041660e082015290565b6040516103a99190614dd2565b34801561050e57600080fd5b5061033d61051d366004614e62565b610fbd565b34801561052e57600080fd5b50601a546040516001600160401b0390911681526020016103a9565b34801561055657600080fd5b5061033d610565366004614e7b565b611050565b34801561057657600080fd5b5061033d6111ec565b34801561058b57600080fd5b5061033d61059a366004614ea7565b61127e565b3480156105ab57600080fd5b5061033d6105ba366004614f04565b61142f565b3480156105cb57600080fd5b5061033d6105da366004614d11565b611529565b3480156105eb57600080fd5b5061033d6105fa366004614d3d565b6115db565b34801561060b57600080fd5b5061061f61061a366004614d3d565b611690565b6040516103a991908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561065e57600080fd5b5061033d61066d366004614f32565b61171e565b34801561067e57600080fd5b5061033d61068d366004614f78565b611803565b34801561069e57600080fd5b5061033d6106ad366004614d76565b611917565b3480156106be57600080fd5b5061039f6106cd366004614fd3565b6119b3565b3480156106de57600080fd5b5061039f6106ed366004614e7b565b6001600160a01b03166000908152600e602052604090205490565b34801561071457600080fd5b5061072861072336600461501a565b611a17565b60405190151581526020016103a9565b34801561074457600080fd5b5061033d610753366004615065565b611a2c565b34801561076457600080fd5b5061033d610773366004614caf565b611c38565b34801561078457600080fd5b5061039f6107933660046150bd565b611d49565b3480156107a457600080fd5b506107fe6107b3366004614e7b565b60408051808201825260008082526020918201819052825180840184528181528083018281526001600160a01b03959095168252600e90925291909120805482526004015490915290565b604080518251815260209283015192810192909252016103a9565b34801561082557600080fd5b5061039f61083436600461501a565b611d9e565b34801561084557600080fd5b5061033d6108543660046150fb565b611e86565b34801561086557600080fd5b5061039f610874366004614d76565b611fb1565b34801561088557600080fd5b5061061f61089436600461501a565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160a01b039788168252601e815284822096881682529586528381209490961686529284529381902081519283018252805483526001810154938301939093526002830154908201526003909101549181019190915290565b34801561092257600080fd5b5061033d610931366004614e7b565b612045565b34801561094257600080fd5b5061033d610951366004614d11565b612161565b34801561096257600080fd5b5061033d610971366004614e62565b6121f2565b34801561098257600080fd5b5061039f610991366004614e7b565b612283565b3480156109a257600080fd5b506109b66109b1366004615180565b61228e565b6040516103a99190615219565b3480156109cf57600080fd5b5061033d6109de366004615299565b612375565b3480156109ef57600080fd5b506107286109fe366004614e7b565b6001600160a01b031660009081526022602052604090205460ff1690565b348015610a2857600080fd5b50610a8b610a37366004614e62565b604080516060808201835260008083526020808401829052928401819052938452601d825292829020825193840183528054845260018101546001600160401b031691840191909152600201549082015290565b60408051825181526020808401516001600160401b03169082015291810151908201526060016103a9565b348015610ac257600080fd5b5061033d610ad1366004615299565b61244e565b348015610ae257600080fd5b5061033d610af1366004614d76565b6124e0565b348015610b0257600080fd5b50610b16610b1136600461501a565b612629565b604051905181526020016103a9565b348015610b3157600080fd5b5061033d61267b565b348015610b4657600080fd5b5061033d610b553660046152d9565b61274d565b348015610b6657600080fd5b5061033d610b75366004614f78565b612bf3565b348015610b8657600080fd5b5061033d612c87565b348015610b9b57600080fd5b5061039f610baa366004614d76565b612d63565b348015610bbb57600080fd5b5061039f610bca366004614d3d565b612e37565b348015610bdb57600080fd5b5060205460ff16610728565b348015610bf357600080fd5b5061033d610c02366004614d76565b612e43565b610c0f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c709190615323565b15610c8e57604051632b37d9d160e21b815260040160405180910390fd5b8484610c9b338383612f2f565b338383909192610cc157604051630c76b97b60e41b81526004016102e093929190615340565b505050610cd18786888787612ff3565b50505050505050565b610ce2612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d439190615323565b15610d6157604051632b37d9d160e21b815260040160405180910390fd5b80600003610d8257604051630a2a4e5b60e11b815260040160405180910390fd5b610db933827f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b03169190613369565b610de6827f0000000000000000000000000000000000000000000000000000000000000000836000613421565b5050565b6000610df68383613656565b90505b92915050565b8282610e0c338383612f2f565b338383909192610e3257604051630c76b97b60e41b81526004016102e093929190615340565b505050610e3d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e9190615323565b15610ebc57604051632b37d9d160e21b815260040160405180910390fd5b610ec785858561368e565b5050505050565b610ed6612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f379190615363565b6001600160a01b0316336001600160a01b031614610f6857604051635d9044cd60e01b815260040160405180910390fd5b601a805467ffffffffffffffff19166001600160401b0383169081179091556040519081527fe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f9060200160405180910390a150565b610fc5612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190615323565b1561104457604051632b37d9d160e21b815260040160405180910390fd5b61104d8161376b565b50565b611058612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611095573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b99190615323565b156110d757604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0381166000908152601b602090815260408083203380855292529091206003810154600160a01b810463ffffffff908116911614158061113d57506003810154600160c01b81046001600160401b039081166401000000009092041614155b156111e7576003810180546401000000006001600160401b03600160c01b63ffffffff19841663ffffffff600160a01b8604811691821792909204831684026bffffffffffffffffffffffff199095161793909317938490556040805193851684529190930490921660208201526001600160a01b0384811692908616917fa4c005afae9298a5ca51e7710c334ac406fb3d914588ade970850f917cedb1c6910160405180910390a35b505050565b6111f4612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190615323565b1561127357604051632b37d9d160e21b815260040160405180910390fd5b61127c3361393e565b565b611286612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190615323565b1561130557604051632b37d9d160e21b815260040160405180910390fd5b8383611312338383612f2f565b33838390919261133857604051630c76b97b60e41b81526004016102e093929190615340565b50505061134883620f4240101590565b839061136a57604051631504950160e21b81526004016102e091815260200190565b506001600160a01b038087166000908152601c60209081526040808320938916835292905290812084918660028111156113a6576113a6615380565b60028111156113b7576113b7615380565b81526020810191909152604001600020558360028111156113da576113da615380565b856001600160a01b0316876001600160a01b03167f3474eba30406cacbfbc5a596a7e471662bbcccf206f8d244dbb6f4cc578c52208660405161141f91815260200190565b60405180910390a4505050505050565b611437612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114989190615363565b6001600160a01b0316336001600160a01b0316146114c957604051635d9044cd60e01b815260040160405180910390fd5b6001600160a01b038216600081815260226020908152604091829020805460ff191685151590811790915591519182527f4542960abc7f2d26dab244fc440acf511e3dd0f5cefad571ca802283b4751bbb91015b60405180910390a25050565b611531612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115929190615323565b156115b057604051632b37d9d160e21b815260040160405180910390fd5b6111e7827f000000000000000000000000000000000000000000000000000000000000000083613a37565b6115e3612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190615323565b1561166257604051632b37d9d160e21b815260040160405180910390fd5b610de6827f000000000000000000000000000000000000000000000000000000000000000083600080613cc8565b6116bb6040518060800160405280600081526020016000815260200160008152602001600081525090565b6116e66040518060800160405280600081526020016000815260200160008152602001600081525090565b60006116f28585613e0e565b600281015483526003810154602084015260058101546040840152600601546060830152509392505050565b611726612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190615323565b156117a557604051632b37d9d160e21b815260040160405180910390fd5b816000036117c657604051630a2a4e5b60e11b815260040160405180910390fd5b6117f133837f0000000000000000000000000000000000000000000000000000000000000000610da9565b6117fd84848484613421565b50505050565b61180b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186c9190615323565b1561188a57604051632b37d9d160e21b815260040160405180910390fd5b8484611897338383612f2f565b3383839091926118bd57604051630c76b97b60e41b81526004016102e093929190615340565b50505086856118cd338383612f2f565b3383839091926118f357604051630c76b97b60e41b81526004016102e093929190615340565b50505061190189898761368e565b61190c898888613e92565b505050505050505050565b61191f612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190615323565b1561199e57604051632b37d9d160e21b815260040160405180910390fd5b6119a88382613ff6565b6111e7838383613e92565b6001600160a01b038084166000908152601c602090815260408083209386168352929052908120818360028111156119ed576119ed615380565b60028111156119fe576119fe615380565b81526020019081526020016000205490505b9392505050565b6000611a24848484612f2f565b949350505050565b611a34612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615323565b15611ab357604051632b37d9d160e21b815260040160405180910390fd5b8383611ac0338383612f2f565b338383909192611ae657604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038681166000908152601b60209081526040808320938916835292905220600381015487908790600160601b90046001600160401b0316611b57576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600381015463ffffffff868116600160a01b90920416141580611b93575060038101546001600160401b03858116600160c01b9092041614155b15610cd1576003810180546001600160401b038616600160c01b026001600160c01b0363ffffffff8916600160a01b02166001600160a01b039283161717909155604051878216918916907fe89cbb9d63ba60af555547b12dde6817283e88cbdd45feb2059f2ba71ea346ba90611c27908990899063ffffffff9290921682526001600160401b0316602082015260400190565b60405180910390a350505050505050565b611c40612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca19190615323565b15611cbf57604051632b37d9d160e21b815260040160405180910390fd5b8484611ccc338383612f2f565b338383909192611cf257604051630c76b97b60e41b81526004016102e093929190615340565b5050506001600160a01b038616600090815260226020526040902054869060ff16611d3b57604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b50610cd18786888787612ff3565b600080611d568585613656565b90506000611d64868661404c565b90506000611d7863ffffffff8616846153ac565b90506000611d86838361406f565b9050611d9281856153c3565b98975050505050505050565b6001600160a01b038084166000908152601e6020908152604080832086851684528252808320938516835292905290812060038101548203611de4576000915050611a10565b6001600160a01b038086166000908152601b60209081526040808320938816835292905290812082545b8015611e7a576000818152601d602052604090206001810154426001600160401b0390911611611e6957600283015460018401548254611e4e91906153ac565b611e5891906153d6565b611e6290856153c3565b9350611e6f565b50611e7a565b600201549050611e0e565b50909695505050505050565b82806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190615363565b6001600160a01b0316336001600160a01b031614611f4b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b60405163623faf6160e01b81526001600160a01b0385169063623faf6190611f7990869086906004016153f8565b600060405180830381600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b5050505050505050565b6000611fbb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201c9190615323565b1561203a57604051632b37d9d160e21b815260040160405180910390fd5b611a24848484613a37565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa9190615363565b6001600160a01b0316336001600160a01b03161461210a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206d757374206265207468652070726f78792061646d696e000060448201526064016102e0565b816001600160a01b03166359fc20bb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561214557600080fd5b505af1158015612159573d6000803e3d6000fd5b505050505050565b612169612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190615323565b156121e857604051632b37d9d160e21b815260040160405180910390fd5b610de68282613ff6565b6121fa612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225b9190615323565b1561227957604051632b37d9d160e21b815260040160405180910390fd5b61104d3382613ff6565b6000610df982614086565b604080516000815260208101909152606090826001600160401b038111156122b8576122b861543a565b6040519080825280602002602001820160405280156122eb57816020015b60608152602001906001900390816122d65790505b50915060005b8381101561236d576123483086868481811061230f5761230f615450565b90506020028101906123219190615466565b85604051602001612334939291906154ac565b6040516020818303038152906040526140d1565b83828151811061235a5761235a615450565b60209081029190910101526001016122f1565b505092915050565b61237d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190615323565b156123fc57604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b038216600090815260226020526040902054829060ff1661244257604051622920f760e21b81526001600160a01b0390911660048201526024016102e0565b506111e7838383614147565b612456612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190615323565b156124d557604051632b37d9d160e21b815260040160405180910390fd5b6111e7838383614147565b6124e8612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125499190615323565b1561256757604051632b37d9d160e21b815260040160405180910390fd5b8060000361258857604051630a2a4e5b60e11b815260040160405180910390fd5b60006125948484613e0e565b90508181600201546125a691906153c3565b60028201556125d633837f0000000000000000000000000000000000000000000000000000000000000000610da9565b826001600160a01b0316846001600160a01b03167f673007a04e501145e79f59aea5e0413b6e88344fdaf10326254530d6a15115308460405161261b91815260200190565b60405180910390a350505050565b60408051602081019091526000815260408051602081019091526000815260006126538686613e0e565b6001600160a01b03851660009081526004909101602052604090205482525090509392505050565b612683612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190615363565b6001600160a01b0316336001600160a01b03161461271557604051635d9044cd60e01b815260040160405180910390fd5b600d805463ffffffff191690556040517f93be484d290d119d9cf99cce69d173c732f9403333ad84f69c807b590203d10990600090a1565b612755612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b69190615323565b156127d457604051632b37d9d160e21b815260040160405180910390fd5b6001600160a01b0384166000908152601b60209081526040808320338085529252822090916128038784613e0e565b905060008160020154836000015461281b91906153c3565b90508087816128465760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506000612854888361406f565b9050600061286685600001548361406f565b90508015612a9d57600385015460009061288b90839063ffffffff9081169061427716565b90508881818110156128b957604051632f514d5760e21b8152600481019290925260248201526044016102e0565b50508815612950576128f8888a7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031691906142de565b876001600160a01b0316876001600160a01b03168c6001600160a01b03167f95ff4196cd75fa49180ba673948ea43935f59e7c4ba101fa09b9fe0ec266d5828c60405161294791815260200190565b60405180910390a45b61298e61295d8a84615427565b7f00000000000000000000000000000000000000000000000000000000000000005b6001600160a01b031690614319565b85546000906129a5670de0b6b3a7640000856153ac565b6129af91906153d6565b9050670de0b6b3a76400006129c48282615427565b88600101546129d391906153ac565b6129dd91906153d6565b600188015586546129ef908490615427565b87556001600160a01b038c166000908152600e6020526040902060040154612a18908490615427565b6001600160a01b038d166000908152600e60205260409020600481019190915554612a44908490615427565b6001600160a01b038d81166000818152600e60209081526040918290209490945551868152918b169290917fe7b110f13cde981d5079ab7faa4249c5f331f5c292dbc6031969d2ce694188a3910160405180910390a350505b612aa78183615427565b91508115612be75760205460ff1615612b9957612ae4827f000000000000000000000000000000000000000000000000000000000000000061297f565b6002840154600090612afe670de0b6b3a7640000856153ac565b612b0891906153d6565b9050828560020154612b1a9190615427565b6002860155670de0b6b3a7640000612b328282615427565b8660050154612b4191906153ac565b612b4b91906153d6565b60058601556040518381526001600160a01b0380891691908d16907fc5d16dbb577cf07678b577232717c9a606197a014f61847e623d47fc6bf6b7719060200160405180910390a350612be7565b856001600160a01b03168a6001600160a01b03167fdce44f0aeed2089c75db59f5a517b9a19a734bf0213412fa129f0d0434126b2484604051612bde91815260200190565b60405180910390a35b50505050505050505050565b612bfb612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190615323565b15612c7a57604051632b37d9d160e21b815260040160405180910390fd5b610ec78585858585613cc8565b612c8f612f0b565b6001600160a01b0316634fc07d756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf09190615363565b6001600160a01b0316336001600160a01b031614612d2157604051635d9044cd60e01b815260040160405180910390fd5b6020805460ff1916600190811782556040519081527f78bd9090b1ff40fc9c2d6056a25fb880530a766f5b0595d77f3cf33fe189c194910160405180910390a1565b6000612d6d612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612daa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dce9190615323565b15612dec57604051632b37d9d160e21b815260040160405180910390fd5b8383612df9338383612f2f565b338383909192612e1f57604051630c76b97b60e41b81526004016102e093929190615340565b505050612e2d868686614361565b9695505050505050565b6000610df6838361404c565b612e4b612f0b565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eac9190615323565b15612eca57604051632b37d9d160e21b815260040160405180910390fd5b8282612ed7338383612f2f565b338383909192612efd57604051630c76b97b60e41b81526004016102e093929190615340565b505050610ec7858585613e92565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000826001600160a01b0316846001600160a01b031603612f5257506001611a10565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612fba57506001600160a01b0380831660009081526015602090815260408083209387168352929052205460ff16611a10565b506001600160a01b038083166000908152601f60209081526040808320858516845282528083209387168352929052205460ff16611a10565b6000841161301457604051630a2a4e5b60e11b815260040160405180910390fd5b81620f424063ffffffff821681101561305057604051633a50e6ff60e01b815263ffffffff9283166004820152911660248201526044016102e0565b5050601a5481906001600160401b039081169082168110156130985760405163ee5602e160e01b81526001600160401b039283166004820152911660248201526044016102e0565b50506001600160a01b038581166000908152601b6020908152604080832093871683529290522060030154600160601b90046001600160401b0316156130f157604051632b542c0d60e11b815260040160405180910390fd5b60006130fc86614086565b905084818082111561312a5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b505060405180610100016040528086815260200160008152602001600081526020018463ffffffff168152602001836001600160401b03168152602001426001600160401b031681526020018463ffffffff168152602001836001600160401b0316815250601b6000886001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a8154816001600160401b0302191690836001600160401b0316021790555060a082015181600301600c6101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160030160146101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160030160186101000a8154816001600160401b0302191690836001600160401b031602179055509050506000600e6000886001600160a01b03166001600160a01b03168152602001908152602001600020905085816004015461330691906153c3565b60048201556040805187815263ffffffff861660208201526001600160401b038516918101919091526001600160a01b0380871691908916907f88b4c2d08cea0f01a24841ff5d14814ddb5b14ac44b05e0835fcc0dcd8c7bc2590606001611c27565b80156111e7576040516323b872dd60e01b81526001600160a01b038381166004830152306024830152604482018390528416906323b872dd906064015b6020604051808303816000875af11580156133c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e99190615323565b6111e75760405162461bcd60e51b815260206004820152600960248201526810ba3930b739b332b960b91b60448201526064016102e0565b81670de0b6b3a7640000808210156134555760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038481166000908152601b602090815260408083209387168352929052206003015484908490600160601b90046001600160401b03166134c4576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b505060006134d28585613e0e565b33600090815260048201602052604090206002820154919250901515806135085750600382015415801561350857506006820154155b8686909161353c57604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b5050600082600201546000148061355a575082600501548360020154145b61359057826005015483600201546135729190615427565b600384015461358190876153ac565b61358b91906153d6565b613592565b845b905080158015906135a35750838110155b818590916135cd57604051635d88e8d160e01b8152600481019290925260248201526044016102e0565b50508483600201546135df91906153c3565b600284015560038301546135f49082906153c3565b600384015581546136069082906153c3565b825560405185815233906001600160a01b0388811691908a16907feaefa9a428d7aa0b99b7ac8aec4885d6304a78cc8d6a78a6c99dd29e9693cdf49060200160405180910390a450505050505050565b6001600160a01b038281166000908152601b60209081526040808320938516835292905290812060018101549054610df69190615427565b6001600160a01b038084166000908152601b602090815260408083209386168352929052908120600281015460018201549192916136d087878184868a6144d6565b8654929550935091506136e4908490615427565b845560028401829055600184018190556001600160a01b0387166000908152600e60205260408120600401805485929061371f908490615427565b92505081905550856001600160a01b0316876001600160a01b03167f9008d731ddfbec70bc364780efd63057c6877bee8027c4708a104b365395885d85604051611c2791815260200190565b33600082900361378e57604051630a2a4e5b60e11b815260040160405180910390fd5b600061379982614086565b90508281808211156137c75760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50506001600160a01b0382166000908152600e602052604081208054600d549192909163ffffffff1690819003613877576138028683615427565b835561382f85877f00000000000000000000000000000000000000000000000000000000000000006128e8565b846001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc8760405161386a91815260200190565b60405180910390a2612159565b60028301541580159061388e575082600301544310155b1561389c5761389c8561393e565b6002830154156138c6576138c36138b7846003015443614616565b84600201548389614630565b90505b8583600201546138d691906153c3565b60028401556138e581436153c3565b6003840181905560028401546040805191825260208201929092526001600160a01b038716917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050505050565b6001600160a01b0381166000908152600e602052604081206002810154909181900361397d57604051630a2a4e5b60e11b815260040160405180910390fd5b6003820154438111156139a657604051631d222f1b60e31b81526004016102e091815260200190565b50600060028301819055600383015581546139c2908290615427565b82556139ef83827f00000000000000000000000000000000000000000000000000000000000000006128e8565b826001600160a01b03167f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc82604051613a2a91815260200190565b60405180910390a2505050565b6000808211613a5957604051637318ad9960e01b815260040160405180910390fd5b6000613a658585613e0e565b33600090815260048201602052604090208054919250908480821015613aa75760405163ab99793560e01b8152600481019290925260248201526044016102e0565b5050600282015486908690613ae257604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000826003015483600501548460020154613aff9190615427565b613b0990876153ac565b613b1391906153d6565b905060008360050154600014613b465760058401546006850154613b3790846153ac565b613b4191906153d6565b613b48565b815b6001600160a01b038981166000908152601b60209081526040808320938c1683529290529081206003015491925090613b929064010000000090046001600160401b0316426153c3565b9050868560030154613ba49190615427565b60038601556005850154613bb99084906153c3565b60058601556006850154613bce9083906153c3565b60068601558354613be0908890615427565b80855515613c53576000856003015486600501548760020154613c039190615427565b8654613c0f91906153ac565b613c1991906153d6565b905080670de0b6b3a764000080821015613c4f5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b5050505b6000613c628a8a338686614684565b9050336001600160a01b0316896001600160a01b03168b6001600160a01b03167f50d19209821f5d69c0884b007c6ba9ffde612c0cff5dd3234d0c6baf2c4556aa87604051613cb391815260200190565b60405180910390a49998505050505050505050565b6000613cd48686613e0e565b905080600201546000141586869091613d1357604051631984edef60e31b81526001600160a01b039283166004820152911660248201526044016102e0565b50506006810154600582015460009190613d3189893384868a6144d6565b600287015492955093509150613d48908490615427565b600285015560068401829055600584018190558215613dac576001600160a01b03871615613d8157613d7c87898589613421565b613dac565b613dac33847f00000000000000000000000000000000000000000000000000000000000000006128e8565b336001600160a01b0316886001600160a01b03168a6001600160a01b03167f305f519d8909c676ffd870495d4563032eb0b506891a6dd9827490256cc9914e86604051613dfb91815260200190565b60405180910390a4505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603613e6757506001600160a01b0382166000908152601460205260409020610df9565b506001600160a01b038083166000908152602160209081526040808320938516835292905220610df9565b6001600160a01b038084166000908152601b60209081526040808320938616835292905290812090829003613eda57604051630a2a4e5b60e11b815260040160405180910390fd5b600381015484908490600160601b90046001600160401b0316613f23576040516330acea0d60e11b81526001600160a01b039283166004820152911660248201526044016102e0565b50506000613f3085614086565b9050828180821115613f5e5760405163ccaf28a960e01b8152600481019290925260248201526044016102e0565b50508154613f6d9084906153c3565b82556001600160a01b0385166000908152600e6020526040902060040154613f969084906153c3565b6001600160a01b038681166000818152600e602090815260409182902060040194909455518681529187169290917feaf6ea3a42ed2fd1b6d575f818cbda593af9524aa94bd30e65302ac4dc234745910160405180910390a35050505050565b8060000361401757604051630a2a4e5b60e11b815260040160405180910390fd5b61404233827f0000000000000000000000000000000000000000000000000000000000000000610da9565b610de68282614824565b6000806140598484613e0e565b905080600501548160020154611a249190615427565b60008183111561407f5781610df6565b5090919050565b6001600160a01b0381166000908152600e602052604081206002810154600182015460048301549254919290916140bd9190615427565b6140c79190615427565b610df99190615427565b6060600080846001600160a01b0316846040516140ee91906154d3565b600060405180830381855af49150503d8060008114614129576040519150601f19603f3d011682016040523d82523d6000602084013e61412e565b606091505b509150915061413e858383614897565b95945050505050565b336001600160a01b0384160361417057604051630123065360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036141dd573360009081526015602090815260408083206001600160a01b03871684529091529020805460ff1916821515179055614219565b336000908152601f602090815260408083206001600160a01b03868116855290835281842090871684529091529020805460ff19168215151790555b816001600160a01b0316836001600160a01b0316336001600160a01b03167faa5a59b38e8f68292982382bf635c2f263ca37137bbc52956acd808fd7bf976f8460405161426a911515815260200190565b60405180910390a4505050565b600061428683620f4240101590565b80614299575061429982620f4240101590565b838390916142c35760405163768bf0eb60e11b8152600481019290925260248201526044016102e0565b50620f424090506142d483856153ac565b610df691906153d6565b80156111e75760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016133a6565b8015610de657604051630852cd8d60e31b8152600481018290526001600160a01b038316906342966c6890602401600060405180830381600087803b15801561214557600080fd5b60008160000361438457604051630a2a4e5b60e11b815260040160405180910390fd5b60006143908585613656565b90508083808210156143be5760405163587ab9ab60e11b8152600481019290925260248201526044016102e0565b50506001600160a01b038086166000908152601b60209081526040808320938816835292905290812060028101549091901561441857816001015485836002015461440991906153ac565b61441391906153d6565b61441a565b845b60038301549091506000906144409064010000000090046001600160401b0316426153c3565b905085836001015461445291906153c3565b600184015560028301546144679083906153c3565b6002840155600061447b8989818686614684565b9050876001600160a01b0316896001600160a01b03167f3b81913739097ced1e7fa748c6058d34e2c00b961fb501094543b397b198fdaa896040516144c291815260200190565b60405180910390a398975050505050505050565b6001600160a01b038087166000908152601e6020908152604080832089851684528252808320938816835292905290812060038101548291829161452d576040516307e332c560e31b815260040160405180910390fd5b6000808061457e6148f3614908614a43868e8e604051602001614563939291909283526020830191909152604082015260600190565b60408051601f1981840301815291905288939291908d614a6d565b915091508080602001905181019061459691906154ef565b809b50819c508295505050508a6001600160a01b03168c6001600160a01b03168e6001600160a01b03167f9de822a9c144d03cad4a18bc322e9a3d91ffa99463d22e5c25da2a41d4c354d585876040516145fa929190918252602082015260400190565b60405180910390a450909b979a50959850959650505050505050565b6000818311614626576000610df6565b610df68284615427565b600061463c82856153c3565b600161464884876153c3565b6146529190615427565b61465c84866153ac565b61466687896153ac565b61467091906153c3565b61467a91906153c3565b61413e91906153d6565b6001600160a01b038086166000908152601e6020908152604080832088851684528252808320938716835292905290812060038101546064116146da5760405163332b852b60e11b815260040160405180910390fd5b60028101546040516bffffffffffffffffffffffff1960608a811b8216602084015289811b8216603484015288901b166048820152605c810191909152600090607c0160408051808303601f1901815282825280516020918201206060840183528884526001600160401b038881168386019081526000868601818152848252601d9095529490942094518555925160018501805467ffffffffffffffff19169190941617909255516002909201919091556003830154909150156147b35760018201546000908152601d602052604090206002018190555b6147bd8282614b27565b604080518681526001600160401b03861660208201529081018290526001600160a01b0380881691898216918b16907f434422e55cc9ab3bcca23cbf515724bbad83af8dd645832a1abd3db5e641dea59060600160405180910390a4979650505050505050565b6001600160a01b0382166000908152600e60205260409020546148489082906153c3565b6001600160a01b0383166000818152600e6020526040908190209290925590517f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc29061151d9084815260200190565b6060826148ac576148a782614bba565b611a10565b81511580156148c357506001600160a01b0384163b155b156148ec57604051639996b31560e01b81526001600160a01b03851660048201526024016102e0565b5080611a10565b6000908152601d602052604090206002015490565b6000828152601d60205260408120600181015460609190426001600160401b03909116111561494b57505060408051602081019091526000815260019150614a3c565b60008060008680602001905181019061496491906154ef565b92509250925060008183866000015461497d91906153ac565b61498791906153d6565b90506149938184615427565b85549093506149a29083615427565b91506149ae81856153c3565b855460018701546040805185815260208101939093526001600160401b0390911682820152519195508a917f65662212afe828a9d3832eda69b6b7b2fb6a756c0f2a7420bf8b290dad84470f9181900360600190a260408051602081018690529081018490526060810183905260800160405160208183030381529060405297506000889650965050505050505b9250929050565b6000908152601d6020526040812081815560018101805467ffffffffffffffff1916905560020155565b600060608760030154831115614a9657604051634a411b9d60e11b815260040160405180910390fd5b60008315614aa45783614aaa565b88600301545b89549094505b8015801590614abf5750600085115b15614b1857600080614ad583898c63ffffffff16565b915091508115614ae6575050614b18565b965086614af48c8c8b614be3565b925086614b008161551d565b9750508380614b0e90615534565b9450505050614ab0565b50989397509295505050505050565b612710826003015410614b4d576040516303a8c56b60e61b815260040160405180910390fd5b80614b6b57604051638f4a893d60e01b815260040160405180910390fd5b6001808301829055600283018054600090614b879084906153c3565b90915550506003820154600003614b9c578082555b6001826003016000828254614bb191906153c3565b90915550505050565b805115614bca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600080846003015411614c095760405163ddaf8f2160e01b815260040160405180910390fd5b6000614c1c85600001548563ffffffff16565b9050614c2f85600001548463ffffffff16565b6001856003016000828254614c449190615427565b90915550508085556003850154600003614c6057600060018601555b5050915492915050565b6001600160a01b038116811461104d57600080fd5b803563ffffffff81168114614c9357600080fd5b919050565b80356001600160401b0381168114614c9357600080fd5b600080600080600060a08688031215614cc757600080fd5b8535614cd281614c6a565b94506020860135614ce281614c6a565b935060408601359250614cf760608701614c7f565b9150614d0560808701614c98565b90509295509295909350565b60008060408385031215614d2457600080fd5b8235614d2f81614c6a565b946020939093013593505050565b60008060408385031215614d5057600080fd5b8235614d5b81614c6a565b91506020830135614d6b81614c6a565b809150509250929050565b600080600060608486031215614d8b57600080fd5b8335614d9681614c6a565b92506020840135614da681614c6a565b929592945050506040919091013590565b600060208284031215614dc957600080fd5b610df682614c98565b60006101008201905082518252602083015160208301526040830151604083015263ffffffff60608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015260c0830151614e4060c084018263ffffffff169052565b5060e0830151614e5b60e08401826001600160401b03169052565b5092915050565b600060208284031215614e7457600080fd5b5035919050565b600060208284031215614e8d57600080fd5b8135611a1081614c6a565b803560038110614c9357600080fd5b60008060008060808587031215614ebd57600080fd5b8435614ec881614c6a565b93506020850135614ed881614c6a565b9250614ee660408601614e98565b9396929550929360600135925050565b801515811461104d57600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614c6a565b91506020830135614d6b81614ef6565b60008060008060808587031215614f4857600080fd5b8435614f5381614c6a565b93506020850135614f6381614c6a565b93969395505050506040820135916060013590565b600080600080600060a08688031215614f9057600080fd5b8535614f9b81614c6a565b94506020860135614fab81614c6a565b93506040860135614fbb81614c6a565b94979396509394606081013594506080013592915050565b600080600060608486031215614fe857600080fd5b8335614ff381614c6a565b9250602084013561500381614c6a565b915061501160408501614e98565b90509250925092565b60008060006060848603121561502f57600080fd5b833561503a81614c6a565b9250602084013561504a81614c6a565b9150604084013561505a81614c6a565b809150509250925092565b6000806000806080858703121561507b57600080fd5b843561508681614c6a565b9350602085013561509681614c6a565b92506150a460408601614c7f565b91506150b260608601614c98565b905092959194509250565b6000806000606084860312156150d257600080fd5b83356150dd81614c6a565b925060208401356150ed81614c6a565b915061501160408501614c7f565b60008060006040848603121561511057600080fd5b833561511b81614c6a565b925060208401356001600160401b0381111561513657600080fd5b8401601f8101861361514757600080fd5b80356001600160401b0381111561515d57600080fd5b86602082840101111561516f57600080fd5b939660209190910195509293505050565b6000806020838503121561519357600080fd5b82356001600160401b038111156151a957600080fd5b8301601f810185136151ba57600080fd5b80356001600160401b038111156151d057600080fd5b8560208260051b84010111156151e557600080fd5b6020919091019590945092505050565b60005b838110156152105781810151838201526020016151f8565b50506000910152565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561528d57603f198786030184528151805180875261526a8160208901602085016151f5565b601f01601f19169590950160209081019550938401939190910190600101615241565b50929695505050505050565b6000806000606084860312156152ae57600080fd5b83356152b981614c6a565b925060208401356152c981614c6a565b9150604084013561505a81614ef6565b600080600080608085870312156152ef57600080fd5b84356152fa81614c6a565b93506020850135925060408501359150606085013561531881614c6a565b939692955090935050565b60006020828403121561533557600080fd5b8151611a1081614ef6565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561537557600080fd5b8151611a1081614c6a565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610df957610df9615396565b80820180821115610df957610df9615396565b6000826153f357634e487b7160e01b600052601260045260246000fd5b500490565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b81810381811115610df957610df9615396565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261547d57600080fd5b8301803591506001600160401b0382111561549757600080fd5b602001915036819003821315614a3c57600080fd5b8284823760008382016000815283516154c98183602088016151f5565b0195945050505050565b600082516154e58184602087016151f5565b9190910192915050565b60008060006060848603121561550457600080fd5b5050815160208301516040909301519094929350919050565b60008161552c5761552c615396565b506000190190565b60006001820161554657615546615396565b506001019056fea264697066735822122006c6e4bfdc1de64a080ef26443cebb679f74b45bd0aaa62e574320a49283676164736f6c634300081b00330000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca000000000000000000000000f203161ba7e25263deb79a4478be18644c2c54460000000000000000000000000000000000000000000000000000000000000000","id":1,"type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStaking#HorizonStaking","networkInteractionId":1,"nonce":594,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xe526d7a57dfcc3b35230960b0593a00429db265e885d76401885b5365d11ad82"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonStaking#HorizonStaking","hash":"0xe526d7a57dfcc3b35230960b0593a00429db265e885d76401885b5365d11ad82","networkInteractionId":1,"receipt":{"blockHash":"0x00aa4ab5d6b7e6d197d4e4a85b88f7663d5576fb0db3cef71211da87839c2aed","blockNumber":82178167,"contractAddress":"0xFf2Ee30de92F276018642A59Fb7Be95b3F9088Af","logs":[{"address":"0xFf2Ee30de92F276018642A59Fb7Be95b3F9088Af","data":"0x000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f0000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea74906340000000000000000000000007975475801bef845f10ce7784dc69ab1e0344f11000000000000000000000000fa8c011255e691aeeb57caa63ccd181e93befe75000000000000000000000000dc427a9ad72c0d9636c7b375e14c3dc39ffaf35d0000000000000000000000000eb1325d7f1a188d5914fddb8566ae513a28d0da0000000000000000000000004594a5915b3aaa78cdf6273a76678855ca675860","logIndex":2,"topics":["0xef5021414834d86e36470f5c1cecf6544fb2bb723f2ca51a4c86fcd8c5919a43","0x0000000000000000000000001a1af8b44fd59dd2bbeb456d1b7604c7bd340702","0x0000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","0x0000000000000000000000004dbe1b10bc15d0f53ff508be01942198262ddfca"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStaking#HorizonStaking","result":{"address":"0xFf2Ee30de92F276018642A59Fb7Be95b3F9088Af","type":"SUCCESS"},"type":"DEPLOYMENT_EXECUTION_STATE_COMPLETE"} +{"args":[],"artifactId":"PaymentsEscrow#PaymentsEscrow","dependencies":["PaymentsEscrow#PaymentsEscrow"],"functionName":"initialize","futureId":"PaymentsEscrow#encodeFunctionCall(PaymentsEscrow#PaymentsEscrow.initialize)","result":"0x8129fc1c","strategy":"basic","strategyConfig":{},"type":"ENCODE_FUNCTION_CALL_EXECUTION_STATE_INITIALIZE"} +{"args":["0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","0xf5B3661BbB8CD48571C7f41ba2D896a3589C9753","0x8129fc1c"],"artifactId":"HorizonProxies#ProxyAdmin_GraphPayments","contractAddress":"0xbb29b876AA2faCEb3af83d768CB03dd3BFF03f5e","dependencies":["HorizonProxies#ProxyAdmin_GraphPayments","HorizonProxies#TransparentUpgradeableProxy_GraphPayments","GraphPayments#GraphPayments","GraphPayments#encodeFunctionCall(GraphPayments#GraphPayments.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"upgradeAndCall","futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","networkInteraction":{"data":"0x9623609d000000000000000000000000c2d72de802dedc8a539f7fd9ff39ad1aa89f7b3f000000000000000000000000f5b3661bbb8cd48571c7f41ba2d896a3589c9753000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000","id":1,"to":"0xbb29b876AA2faCEb3af83d768CB03dd3BFF03f5e","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","networkInteractionId":1,"nonce":595,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xed1cf6b814c8a31532b003821d02f969f902b550cd17a4df4f1119963222ff8f"},"type":"TRANSACTION_SEND"} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","hash":"0xed1cf6b814c8a31532b003821d02f969f902b550cd17a4df4f1119963222ff8f","networkInteractionId":1,"receipt":{"blockHash":"0xa69bfc6af51ef4a1230b0cbaa09adcecf9ad2216d6f5c4c3a373bd0ebfee8ef8","blockNumber":82178183,"logs":[{"address":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","data":"0x","logIndex":0,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x000000000000000000000000f5b3661bbb8cd48571c7f41ba2d896a3589c9753"]},{"address":"0xC2D72de802deDC8A539F7FD9fF39aD1aA89F7b3f","data":"0x0000000000000000000000000000000000000000000000000000000000000001","logIndex":1,"topics":["0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"GraphPayments#HorizonProxies~ProxyAdmin_GraphPayments.upgradeAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","0xFf2Ee30de92F276018642A59Fb7Be95b3F9088Af"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","HorizonProxies#GraphProxy_HorizonStaking","HorizonStaking#HorizonStaking"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"upgrade","futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","networkInteraction":{"data":"0x99a88ec40000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf000000000000000000000000ff2ee30de92f276018642a59fb7be95b3f9088af","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","networkInteractionId":1,"nonce":596,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x7cf329f1474b4fe182d4364502f16e2b42ae1670df0a0b92efdf02f130612a28"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","hash":"0x7cf329f1474b4fe182d4364502f16e2b42ae1670df0a0b92efdf02f130612a28","networkInteractionId":1,"receipt":{"blockHash":"0x6a5bdf09bd426cb6eff2de4b276f8f7651b9f3545e439f1a09940361fc6d0db7","blockNumber":82178196,"logs":[{"address":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","data":"0x","logIndex":1,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ff2ee30de92f276018642a59fb7be95b3f9088af"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","0x09B985a2042848A08bA59060EaF0f07c6F5D4d54","0x8129fc1c"],"artifactId":"HorizonProxies#ProxyAdmin_PaymentsEscrow","contractAddress":"0x6D892d831196E1Ad3779B97320b7091dE7d45053","dependencies":["HorizonProxies#ProxyAdmin_PaymentsEscrow","HorizonProxies#TransparentUpgradeableProxy_PaymentsEscrow","PaymentsEscrow#PaymentsEscrow","PaymentsEscrow#encodeFunctionCall(PaymentsEscrow#PaymentsEscrow.initialize)"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"upgradeAndCall","futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","networkInteraction":{"data":"0x9623609d0000000000000000000000005904ab9c7806fcc7634f1dcdbec544eea749063400000000000000000000000009b985a2042848a08ba59060eaf0f07c6f5d4d54000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000","id":1,"to":"0x6D892d831196E1Ad3779B97320b7091dE7d45053","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","networkInteractionId":1,"nonce":597,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x7f98e4168aa1e6306b2f3c93e340752a0cbaba45cc354d7a2703b943e5a370b4"},"type":"TRANSACTION_SEND"} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","hash":"0x7f98e4168aa1e6306b2f3c93e340752a0cbaba45cc354d7a2703b943e5a370b4","networkInteractionId":1,"receipt":{"blockHash":"0x6b4134d93d6088ca8f3c0c972217fc205da35723b88fc2c626a366cfae70b5da","blockNumber":82178210,"logs":[{"address":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","data":"0x","logIndex":0,"topics":["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b","0x00000000000000000000000009b985a2042848a08ba59060eaf0f07c6f5d4d54"]},{"address":"0x5904ab9c7806FCC7634F1DcDBec544eEa7490634","data":"0x0000000000000000000000000000000000000000000000000000000000000001","logIndex":1,"topics":["0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"PaymentsEscrow#HorizonProxies~ProxyAdmin_PaymentsEscrow.upgradeAndCall","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":["0xFf2Ee30de92F276018642A59Fb7Be95b3F9088Af","0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf"],"artifactId":"GraphProxyAdmin#GraphProxyAdmin","contractAddress":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","dependencies":["GraphProxyAdmin#GraphProxyAdmin","HorizonStaking#HorizonStaking","HorizonProxies#GraphProxy_HorizonStaking","HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.upgrade"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"acceptProxy","futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","networkInteraction":{"data":"0xeb451a02000000000000000000000000ff2ee30de92f276018642a59fb7be95b3f9088af0000000000000000000000003f53f9f9a5d7f36dcc869f8d2f227499c411c0cf","id":1,"to":"0x0eb1325d7F1a188D5914fddb8566aE513A28D0da","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","networkInteractionId":1,"nonce":598,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x35fbdfb81b5a57e9dfd298d6b34183a2c34a929f83149518964bff0e6eefb8da"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","hash":"0x35fbdfb81b5a57e9dfd298d6b34183a2c34a929f83149518964bff0e6eefb8da","networkInteractionId":1,"receipt":{"blockHash":"0xe266d5efaaf677777116f93a2f74d85ba61e8da75da4e8ed8f4856bfc382faf5","blockNumber":82178231,"logs":[{"address":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","data":"0x","logIndex":0,"topics":["0xaa3f731066a578e5f39b4215468d826cdd15373cbc0dfc9cb9bdc649718ef7da","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000ff2ee30de92f276018642a59fb7be95b3f9088af"]},{"address":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","data":"0x","logIndex":1,"topics":["0x980c0d30fe97457c47903527d88b7009a1643be6de24d2af664214919f0540a1","0x000000000000000000000000ff2ee30de92f276018642a59fb7be95b3f9088af","0x0000000000000000000000000000000000000000000000000000000000000000"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"artifactId":"HorizonStaking#HorizonStaking_Instance","contractAddress":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","contractName":"HorizonStaking","dependencies":["HorizonStaking#GraphProxyAdmin~GraphProxyAdmin.acceptProxy","HorizonProxies#GraphProxy_HorizonStaking"],"futureId":"HorizonStaking#HorizonStaking_Instance","futureType":"CONTRACT_AT","strategy":"basic","strategyConfig":{},"type":"CONTRACT_AT_EXECUTION_STATE_INITIALIZE"} +{"args":[2419200],"artifactId":"HorizonStaking#HorizonStaking_Instance","contractAddress":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","dependencies":["HorizonStaking#HorizonStaking_Instance"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setMaxThawingPeriod","futureId":"HorizonStaking#HorizonStaking_Instance.setMaxThawingPeriod","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"HorizonStaking#HorizonStaking_Instance.setMaxThawingPeriod","networkInteraction":{"data":"0x259bc435000000000000000000000000000000000000000000000000000000000024ea00","id":1,"to":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"HorizonStaking#HorizonStaking_Instance.setMaxThawingPeriod","networkInteractionId":1,"nonce":601,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0x9fd8876526dfaba8d3a68beec3849237f3c28e5f1456bec14dc462633b3c14b5"},"type":"TRANSACTION_SEND"} +{"futureId":"HorizonStaking#HorizonStaking_Instance.setMaxThawingPeriod","hash":"0x9fd8876526dfaba8d3a68beec3849237f3c28e5f1456bec14dc462633b3c14b5","networkInteractionId":1,"receipt":{"blockHash":"0xcd3553308f6e624653fa73232c1576e4e71fc925645eed70469412d5e3b2561b","blockNumber":83711037,"logs":[{"address":"0x3F53F9f9a5d7F36dCC869f8D2F227499c411c0cf","data":"0x000000000000000000000000000000000000000000000000000000000024ea00","logIndex":6,"topics":["0xe8526be46fa99b6313d439293c9be3491ffb067741bc8fce9d30c270cbb8459f"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"HorizonStaking#HorizonStaking_Instance.setMaxThawingPeriod","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} +{"args":[false],"artifactId":"Controller#Controller","contractAddress":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","dependencies":["Controller#Controller"],"from":"0xade6b8eb69a49b56929c1d4f4b428d791861db6f","functionName":"setPaused","futureId":"Controller#Controller.setPaused","strategy":"basic","strategyConfig":{},"type":"CALL_EXECUTION_STATE_INITIALIZE","value":{"_kind":"bigint","value":"0"}} +{"futureId":"Controller#Controller.setPaused","networkInteraction":{"data":"0x16c38b3c0000000000000000000000000000000000000000000000000000000000000000","id":1,"to":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","type":"ONCHAIN_INTERACTION","value":{"_kind":"bigint","value":"0"}},"type":"NETWORK_INTERACTION_REQUEST"} +{"futureId":"Controller#Controller.setPaused","networkInteractionId":1,"nonce":602,"transaction":{"fees":{"maxFeePerGas":{"_kind":"bigint","value":"200000000"},"maxPriorityFeePerGas":{"_kind":"bigint","value":"0"}},"hash":"0xd75a4e87b6a1b53ab1d9e9c010fc33ad70bb11812a9c7b7f2a590cfbf9fa82b6"},"type":"TRANSACTION_SEND"} +{"futureId":"Controller#Controller.setPaused","hash":"0xd75a4e87b6a1b53ab1d9e9c010fc33ad70bb11812a9c7b7f2a590cfbf9fa82b6","networkInteractionId":1,"receipt":{"blockHash":"0x7a0e9751569815a889ab35f9384aa9784369c8a50f4a3d8fb23568093e1ff514","blockNumber":83746020,"logs":[{"address":"0x4DbE1B10bc15D0F53fF508BE01942198262ddfCa","data":"0x0000000000000000000000000000000000000000000000000000000000000000","logIndex":3,"topics":["0x8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec5"]}],"status":"SUCCESS"},"type":"TRANSACTION_CONFIRM"} +{"futureId":"Controller#Controller.setPaused","result":{"type":"SUCCESS"},"type":"CALL_EXECUTION_STATE_COMPLETE"} \ No newline at end of file diff --git a/packages/horizon/ignition/modules/core.ts b/packages/horizon/ignition/modules/core.ts new file mode 100644 index 000000000..eb949e475 --- /dev/null +++ b/packages/horizon/ignition/modules/core.ts @@ -0,0 +1,15 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphPaymentsModule from './core/GraphPayments' +import HorizonStakingModule from './core/HorizonStaking' +import PaymentsEscrowModule from './core/PaymentsEscrow' +import TAPCollectorModule from './core/TAPCollector' + +export default buildModule('GraphHorizon_Core', (m) => { + const { HorizonStaking } = m.useModule(HorizonStakingModule) + const { GraphPayments } = m.useModule(GraphPaymentsModule) + const { PaymentsEscrow } = m.useModule(PaymentsEscrowModule) + const { TAPCollector } = m.useModule(TAPCollectorModule) + + return { HorizonStaking, GraphPayments, PaymentsEscrow, TAPCollector } +}) diff --git a/packages/horizon/ignition/modules/core/GraphPayments.ts b/packages/horizon/ignition/modules/core/GraphPayments.ts new file mode 100644 index 000000000..43fcf5b55 --- /dev/null +++ b/packages/horizon/ignition/modules/core/GraphPayments.ts @@ -0,0 +1,31 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphPeripheryModule from '../periphery' +import HorizonProxiesModule from './HorizonProxies' + +import GraphPaymentsArtifact from '../../../build/contracts/contracts/payments/GraphPayments.sol/GraphPayments.json' + +// TODO: transfer ownership of ProxyAdmin??? +export default buildModule('GraphPayments', (m) => { + const { Controller, PeripheryRegistered } = m.useModule(GraphPeripheryModule) + const { GraphPaymentsProxyAdmin, GraphPaymentsProxy, HorizonRegistered } = m.useModule(HorizonProxiesModule) + + const protocolPaymentCut = m.getParameter('protocolPaymentCut') + + // Deploy GraphPayments implementation + const GraphPaymentsImplementation = m.contract('GraphPayments', + GraphPaymentsArtifact, + [Controller, protocolPaymentCut], + { + after: [PeripheryRegistered, HorizonRegistered], + }, + ) + + // Upgrade proxy to implementation contract + m.call(GraphPaymentsProxyAdmin, 'upgradeAndCall', [GraphPaymentsProxy, GraphPaymentsImplementation, m.encodeFunctionCall(GraphPaymentsImplementation, 'initialize', [])]) + + // Load contract with implementation ABI + const GraphPayments = m.contractAt('GraphPayments', GraphPaymentsArtifact, GraphPaymentsProxy, { id: 'GraphPayments_Instance' }) + + return { GraphPayments } +}) diff --git a/packages/horizon/ignition/modules/core/HorizonProxies.ts b/packages/horizon/ignition/modules/core/HorizonProxies.ts new file mode 100644 index 000000000..8656571af --- /dev/null +++ b/packages/horizon/ignition/modules/core/HorizonProxies.ts @@ -0,0 +1,42 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' +import { deployWithOZProxy } from '../proxy/TransparentUpgradeableProxy' +import { ethers } from 'ethers' + +import GraphPeripheryModule from '../periphery' +import GraphProxyAdminModule from '../periphery/GraphProxyAdmin' + +import DummyArtifact from '../../../build/contracts/contracts/mocks/Dummy.sol/Dummy.json' +import GraphProxyArtifact from '@graphprotocol/contracts/build/contracts/contracts/upgrades/GraphProxy.sol/GraphProxy.json' + +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' + +// HorizonStaking, GraphPayments and PaymentsEscrow use GraphDirectory but they also in the directory. +// So we need to deploy their proxies, register them in the controller before being able to deploy the implementations +export default buildModule('HorizonProxies', (m) => { + const { Controller, PeripheryRegistered } = m.useModule(GraphPeripheryModule) + const { GraphProxyAdmin } = m.useModule(GraphProxyAdminModule) + + // Deploy HorizonStaking proxy without an implementation + const HorizonStakingProxy = m.contract('GraphProxy', GraphProxyArtifact, [ZERO_ADDRESS, GraphProxyAdmin], { after: [PeripheryRegistered], id: 'GraphProxy_HorizonStaking' }) + + // Deploy proxies for payments contracts using OZ TransparentUpgradeableProxy + const { Proxy: GraphPaymentsProxy, ProxyAdmin: GraphPaymentsProxyAdmin } = deployWithOZProxy(m, 'GraphPayments') + const { Proxy: PaymentsEscrowProxy, ProxyAdmin: PaymentsEscrowProxyAdmin } = deployWithOZProxy(m, 'PaymentsEscrow') + + // Register the proxies in the controller + const setProxyHorizonStaking = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('Staking')), HorizonStakingProxy], { id: 'setContractProxy_HorizonStaking' }) + const setProxyGraphPayments = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('GraphPayments')), GraphPaymentsProxy], { id: 'setContractProxy_GraphPayments' }) + const setProxyPaymentsEscrow = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('PaymentsEscrow')), PaymentsEscrowProxy], { id: 'setContractProxy_PaymentsEscrow' }) + + // Deploy dummy contract to signal that all periphery contracts are registered + const HorizonRegistered = m.contract('Dummy', DummyArtifact, [], { + id: 'RegisteredDummy', + after: [ + setProxyHorizonStaking, + setProxyGraphPayments, + setProxyPaymentsEscrow, + ], + }) + + return { HorizonStakingProxy, GraphPaymentsProxy, PaymentsEscrowProxy, HorizonRegistered, GraphPaymentsProxyAdmin, PaymentsEscrowProxyAdmin } +}) diff --git a/packages/horizon/ignition/modules/core/HorizonStaking.ts b/packages/horizon/ignition/modules/core/HorizonStaking.ts new file mode 100644 index 000000000..c412af887 --- /dev/null +++ b/packages/horizon/ignition/modules/core/HorizonStaking.ts @@ -0,0 +1,38 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphPeripheryModule from '../periphery' +import HorizonProxiesModule from './HorizonProxies' +import HorizonStakingExtensionModule from './HorizonStakingExtension' + +import HorizonStakingArtifact from '../../../build/contracts/contracts/staking/HorizonStaking.sol/HorizonStaking.json' + +export default buildModule('HorizonStaking', (m) => { + const { Controller, GraphProxyAdmin, PeripheryRegistered } = m.useModule(GraphPeripheryModule) + const { HorizonStakingProxy, HorizonRegistered } = m.useModule(HorizonProxiesModule) + const { HorizonStakingExtension } = m.useModule(HorizonStakingExtensionModule) + + const subgraphServiceAddress = m.getParameter('subgraphServiceAddress') + + // Deploy HorizonStaking implementation + const HorizonStakingImplementation = m.contract('HorizonStaking', + HorizonStakingArtifact, + [ + Controller, + HorizonStakingExtension, + subgraphServiceAddress, + ], + { + after: [PeripheryRegistered, HorizonRegistered], + }, + ) + + // Upgrade proxy to implementation contract + const upgradeCall = m.call(GraphProxyAdmin, 'upgrade', [HorizonStakingProxy, HorizonStakingImplementation]) + const acceptCall = m.call(GraphProxyAdmin, 'acceptProxy', [HorizonStakingImplementation, HorizonStakingProxy], { after: [upgradeCall] }) + + // Load contract with implementation ABI + const HorizonStaking = m.contractAt('HorizonStaking', HorizonStakingArtifact, HorizonStakingProxy, { after: [acceptCall], id: 'HorizonStaking_Instance' }) + m.call(HorizonStaking, 'setMaxThawingPeriod', [m.getParameter('maxThawingPeriod')]) + + return { HorizonStakingProxy, HorizonStakingImplementation, HorizonStaking } +}) diff --git a/packages/horizon/ignition/modules/core/HorizonStakingExtension.ts b/packages/horizon/ignition/modules/core/HorizonStakingExtension.ts new file mode 100644 index 000000000..f1da04286 --- /dev/null +++ b/packages/horizon/ignition/modules/core/HorizonStakingExtension.ts @@ -0,0 +1,26 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphPeripheryModule from '../periphery' +import HorizonProxiesModule from './HorizonProxies' + +import ExponentialRebatesArtifact from '../../../build/contracts/contracts/staking/libraries/ExponentialRebates.sol/ExponentialRebates.json' +import HorizonStakingExtensionArtifact from '../../../build/contracts/contracts/staking/HorizonStakingExtension.sol/HorizonStakingExtension.json' + +export default buildModule('HorizonStakingExtension', (m) => { + const { Controller, PeripheryRegistered } = m.useModule(GraphPeripheryModule) + const { HorizonRegistered } = m.useModule(HorizonProxiesModule) + + const subgraphServiceAddress = m.getParameter('subgraphServiceAddress') + + const ExponentialRebates = m.library('ExponentialRebates', ExponentialRebatesArtifact) + const HorizonStakingExtension = m.contract('HorizonStakingExtension', + HorizonStakingExtensionArtifact, + [Controller, subgraphServiceAddress], { + libraries: { + ExponentialRebates: ExponentialRebates, + }, + after: [PeripheryRegistered, HorizonRegistered], + }) + + return { HorizonStakingExtension } +}) diff --git a/packages/horizon/ignition/modules/core/PaymentsEscrow.ts b/packages/horizon/ignition/modules/core/PaymentsEscrow.ts new file mode 100644 index 000000000..1dbd07088 --- /dev/null +++ b/packages/horizon/ignition/modules/core/PaymentsEscrow.ts @@ -0,0 +1,32 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphPeripheryModule from '../periphery' +import HorizonProxiesModule from './HorizonProxies' + +import PaymentsEscrowArtifact from '../../../build/contracts/contracts/payments/PaymentsEscrow.sol/PaymentsEscrow.json' + +// TODO: transfer ownership of ProxyAdmin??? +export default buildModule('PaymentsEscrow', (m) => { + const { Controller, PeripheryRegistered } = m.useModule(GraphPeripheryModule) + const { PaymentsEscrowProxyAdmin, PaymentsEscrowProxy, HorizonRegistered } = m.useModule(HorizonProxiesModule) + + const revokeCollectorThawingPeriod = m.getParameter('revokeCollectorThawingPeriod') + const withdrawEscrowThawingPeriod = m.getParameter('withdrawEscrowThawingPeriod') + + // Deploy PaymentsEscrow implementation + const PaymentsEscrowImplementation = m.contract('PaymentsEscrow', + PaymentsEscrowArtifact, + [Controller, revokeCollectorThawingPeriod, withdrawEscrowThawingPeriod], + { + after: [PeripheryRegistered, HorizonRegistered], + }, + ) + + // Upgrade proxy to implementation contract + m.call(PaymentsEscrowProxyAdmin, 'upgradeAndCall', [PaymentsEscrowProxy, PaymentsEscrowImplementation, m.encodeFunctionCall(PaymentsEscrowImplementation, 'initialize', [])]) + + // Load contract with implementation ABI + const PaymentsEscrow = m.contractAt('PaymentsEscrow', PaymentsEscrowArtifact, PaymentsEscrowProxy, { id: 'PaymentsEscrow_Instance' }) + + return { PaymentsEscrow } +}) diff --git a/packages/horizon/ignition/modules/core/TAPCollector.ts b/packages/horizon/ignition/modules/core/TAPCollector.ts new file mode 100644 index 000000000..429dc5083 --- /dev/null +++ b/packages/horizon/ignition/modules/core/TAPCollector.ts @@ -0,0 +1,18 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphPeripheryModule from '../periphery' +import HorizonProxiesModule from './HorizonProxies' + +import TAPCollectorArtifact from '../../../build/contracts/contracts/payments/collectors/TAPCollector.sol/TAPCollector.json' + +export default buildModule('TAPCollector', (m) => { + const { Controller, PeripheryRegistered } = m.useModule(GraphPeripheryModule) + const { HorizonRegistered } = m.useModule(HorizonProxiesModule) + + const name = m.getParameter('eip712Name') + const version = m.getParameter('eip712Version') + + const TAPCollector = m.contract('TAPCollector', TAPCollectorArtifact, [name, version, Controller], { after: [PeripheryRegistered, HorizonRegistered] }) + + return { TAPCollector } +}) diff --git a/packages/horizon/ignition/modules/horizon.ts b/packages/horizon/ignition/modules/horizon.ts new file mode 100644 index 000000000..c68ce88b4 --- /dev/null +++ b/packages/horizon/ignition/modules/horizon.ts @@ -0,0 +1,31 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphHorizonCoreModule from './core' +import GraphPeripheryModule from './periphery' + +export default buildModule('GraphHorizon', (m) => { + const { + BridgeEscrow, + Controller, + EpochManager, + GraphProxyAdmin, + GraphTokenGateway, + RewardsManager, + Curation, + } = m.useModule(GraphPeripheryModule) + const { HorizonStaking, GraphPayments, PaymentsEscrow, TAPCollector } = m.useModule(GraphHorizonCoreModule) + + return { + BridgeEscrow, + Controller, + Curation, + EpochManager, + GraphProxyAdmin, + GraphTokenGateway, + RewardsManager, + HorizonStaking, + GraphPayments, + PaymentsEscrow, + TAPCollector, + } +}) diff --git a/packages/horizon/ignition/modules/periphery.ts b/packages/horizon/ignition/modules/periphery.ts new file mode 100644 index 000000000..2c358c74f --- /dev/null +++ b/packages/horizon/ignition/modules/periphery.ts @@ -0,0 +1,57 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' +import { ethers } from 'ethers' + +import BridgeEscrowModule from './periphery/BridgeEscrow' +import ControllerModule from './periphery/Controller' +import CurationModule from './periphery/Curation' +import EpochManagerModule from './periphery/EpochManager' +import GraphProxyAdminModule from './periphery/GraphProxyAdmin' +import GraphTokenGatewayModule from './periphery/GraphTokenGateway' +import GraphTokenModule from './periphery/GraphToken' +import RewardsManagerModule from './periphery/RewardsManager' + +import DummyArtifact from '../../build/contracts/contracts/mocks/Dummy.sol/Dummy.json' + +export default buildModule('GraphHorizon_Periphery', (m) => { + const { BridgeEscrow } = m.useModule(BridgeEscrowModule) + const { Controller } = m.useModule(ControllerModule) + const { EpochManager } = m.useModule(EpochManagerModule) + const { GraphProxyAdmin } = m.useModule(GraphProxyAdminModule) + const { GraphTokenGateway } = m.useModule(GraphTokenGatewayModule) + const { RewardsManager } = m.useModule(RewardsManagerModule) + const { GraphToken } = m.useModule(GraphTokenModule) + const { Curation } = m.useModule(CurationModule) + + // Register contracts in the Controller + const setProxyEpochManager = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('EpochManager')), EpochManager], { id: 'setContractProxy_EpochManager' }) + const setProxyRewardsManager = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('RewardsManager')), RewardsManager], { id: 'setContractProxy_RewardsManager' }) + const setProxyGraphToken = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('GraphToken')), GraphToken], { id: 'setContractProxy_GraphToken' }) + const setProxyGraphTokenGateway = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('GraphTokenGateway')), GraphTokenGateway], { id: 'setContractProxy_GraphTokenGateway' }) + // eslint-disable-next-line no-secrets/no-secrets + const setProxyGraphProxyAdmin = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('GraphProxyAdmin')), GraphProxyAdmin], { id: 'setContractProxy_GraphProxyAdmin' }) + const setProxyCuration = m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('Curation')), Curation], { id: 'setContractProxy_Curation' }) + + // Deploy dummy contract to signal that all periphery contracts are registered + const PeripheryRegistered = m.contract('Dummy', DummyArtifact, [], { + after: [ + setProxyEpochManager, + setProxyRewardsManager, + setProxyGraphToken, + setProxyGraphTokenGateway, + setProxyGraphProxyAdmin, + setProxyCuration, + ], + }) + + return { + BridgeEscrow, + Controller, + Curation, + EpochManager, + GraphProxyAdmin, + GraphToken, + GraphTokenGateway, + RewardsManager, + PeripheryRegistered, + } +}) diff --git a/packages/horizon/ignition/modules/periphery/BridgeEscrow.ts b/packages/horizon/ignition/modules/periphery/BridgeEscrow.ts new file mode 100644 index 000000000..6d9dd32ee --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/BridgeEscrow.ts @@ -0,0 +1,18 @@ +import { buildModule } from '@nomicfoundation/ignition-core' + +import { deployWithGraphProxy } from '../proxy/GraphProxy' + +import BridgeEscrowArtifact from '@graphprotocol/contracts/build/contracts/contracts/gateway/BridgeEscrow.sol/BridgeEscrow.json' +import ControllerModule from '../periphery/Controller' + +export default buildModule('BridgeEscrow', (m) => { + const { Controller } = m.useModule(ControllerModule) + + const { instance: BridgeEscrow } = deployWithGraphProxy(m, { + name: 'BridgeEscrow', + artifact: BridgeEscrowArtifact, + args: [Controller], + }) + + return { BridgeEscrow } +}) diff --git a/packages/horizon/ignition/modules/periphery/Controller.ts b/packages/horizon/ignition/modules/periphery/Controller.ts new file mode 100644 index 000000000..41a3e6484 --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/Controller.ts @@ -0,0 +1,17 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import ControllerArtifact from '@graphprotocol/contracts/build/contracts/contracts/governance/Controller.sol/Controller.json' + +// TODO: Ownership transfer is a two step process, the new owner needs to accept it by calling acceptOwnership +export default buildModule('Controller', (m) => { + const governor = m.getParameter('governor') + const pauseGuardian = m.getParameter('pauseGuardian') + + const Controller = m.contract('Controller', ControllerArtifact) + + m.call(Controller, 'setPauseGuardian', [pauseGuardian]) + m.call(Controller, 'transferOwnership', [governor]) + m.call(Controller, 'setPaused', [false]) + + return { Controller } +}) diff --git a/packages/horizon/ignition/modules/periphery/Curation.ts b/packages/horizon/ignition/modules/periphery/Curation.ts new file mode 100644 index 000000000..2a1516168 --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/Curation.ts @@ -0,0 +1,23 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' +import { deployWithGraphProxy } from '../proxy/GraphProxy' + +import ControllerModule from './Controller' +import CurationArtifact from '@graphprotocol/contracts/build/contracts/contracts/l2/curation/L2Curation.sol/L2Curation.json' +import GraphCurationTokenArtifact from '@graphprotocol/contracts/build/contracts/contracts/curation/GraphCurationToken.sol/GraphCurationToken.json' + +export default buildModule('Curation', (m) => { + const { Controller } = m.useModule(ControllerModule) + + const curationTaxPercentage = m.getParameter('curationTaxPercentage') + const minimumCurationDeposit = m.getParameter('minimumCurationDeposit') + + const GraphCurationToken = m.contract('GraphCurationToken', GraphCurationTokenArtifact, []) + + const { instance: Curation } = deployWithGraphProxy(m, { + name: 'Curation', + artifact: CurationArtifact, + args: [Controller, GraphCurationToken, curationTaxPercentage, minimumCurationDeposit], + }) + + return { Curation } +}) diff --git a/packages/horizon/ignition/modules/periphery/EpochManager.ts b/packages/horizon/ignition/modules/periphery/EpochManager.ts new file mode 100644 index 000000000..e05792171 --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/EpochManager.ts @@ -0,0 +1,19 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' +import { deployWithGraphProxy } from '../proxy/GraphProxy' + +import ControllerModule from './Controller' +import EpochManagerArtifact from '@graphprotocol/contracts/build/contracts/contracts/epochs/EpochManager.sol/EpochManager.json' + +export default buildModule('EpochManager', (m) => { + const { Controller } = m.useModule(ControllerModule) + + const epochLength = m.getParameter('epochLength') + + const { instance: EpochManager } = deployWithGraphProxy(m, { + name: 'EpochManager', + artifact: EpochManagerArtifact, + args: [Controller, epochLength], + }) + + return { EpochManager } +}) diff --git a/packages/horizon/ignition/modules/periphery/GraphProxyAdmin.ts b/packages/horizon/ignition/modules/periphery/GraphProxyAdmin.ts new file mode 100644 index 000000000..8715316c8 --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/GraphProxyAdmin.ts @@ -0,0 +1,13 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import GraphProxyAdminArtifact from '@graphprotocol/contracts/build/contracts/contracts/upgrades/GraphProxyAdmin.sol/GraphProxyAdmin.json' + +// TODO: Ownership transfer is a two step process, the new owner needs to accept it by calling acceptOwnership +export default buildModule('GraphProxyAdmin', (m) => { + const governor = m.getParameter('governor') + const GraphProxyAdmin = m.contract('GraphProxyAdmin', GraphProxyAdminArtifact) + + m.call(GraphProxyAdmin, 'transferOwnership', [governor]) + + return { GraphProxyAdmin } +}) diff --git a/packages/horizon/ignition/modules/periphery/GraphToken.ts b/packages/horizon/ignition/modules/periphery/GraphToken.ts new file mode 100644 index 000000000..955d95edb --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/GraphToken.ts @@ -0,0 +1,33 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' +import { deployWithGraphProxy } from '../proxy/GraphProxy' + +import GraphTokenGatewayModule from '../periphery/GraphTokenGateway' +import RewardsManagerModule from '../periphery/RewardsManager' + +import GraphTokenArtifact from '@graphprotocol/contracts/build/contracts/contracts/l2/token/L2GraphToken.sol/L2GraphToken.json' + +// TODO: Ownership transfer is a two step process, the new owner needs to accept it by calling acceptOwnership +export default buildModule('GraphToken', (m) => { + const { RewardsManager } = m.useModule(RewardsManagerModule) + const { GraphTokenGateway } = m.useModule(GraphTokenGatewayModule) + + const deployer = m.getAccount(0) + const governor = m.getParameter('governor') + const initialSupply = m.getParameter('initialSupply') + + const { instance: GraphToken } = deployWithGraphProxy(m, { + name: 'GraphToken', + artifact: GraphTokenArtifact, + args: [deployer], + }) + + // TODO: move this mint to a testnet only module + // Note that this next mint would only be done in L1 + m.call(GraphToken, 'mint', [deployer, initialSupply]) + m.call(GraphToken, 'renounceMinter', []) + m.call(GraphToken, 'addMinter', [RewardsManager], { id: 'addMinterRewardsManager' }) + m.call(GraphToken, 'addMinter', [GraphTokenGateway], { id: 'addMinterGateway' }) + m.call(GraphToken, 'transferOwnership', [governor]) + + return { GraphToken } +}) diff --git a/packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts b/packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts new file mode 100644 index 000000000..2bb13a78e --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts @@ -0,0 +1,22 @@ +import { buildModule } from '@nomicfoundation/ignition-core' + +import { deployWithGraphProxy } from '../proxy/GraphProxy' + +import ControllerModule from '../periphery/Controller' +import GraphTokenGatewayArtifact from '@graphprotocol/contracts/build/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol/L2GraphTokenGateway.json' + +export default buildModule('GraphTokenGateway', (m) => { + const { Controller } = m.useModule(ControllerModule) + + const pauseGuardian = m.getParameter('pauseGuardian') + + const { instance: GraphTokenGateway } = deployWithGraphProxy(m, { + name: 'GraphTokenGateway', + artifact: GraphTokenGatewayArtifact, + args: [Controller], + }) + + m.call(GraphTokenGateway, 'setPauseGuardian', [pauseGuardian]) + + return { GraphTokenGateway } +}) diff --git a/packages/horizon/ignition/modules/periphery/RewardsManager.ts b/packages/horizon/ignition/modules/periphery/RewardsManager.ts new file mode 100644 index 000000000..3773933e9 --- /dev/null +++ b/packages/horizon/ignition/modules/periphery/RewardsManager.ts @@ -0,0 +1,26 @@ +import { buildModule } from '@nomicfoundation/ignition-core' + +import { deployWithGraphProxy } from '../proxy/GraphProxy' + +import ControllerModule from '../periphery/Controller' +import RewardsManagerArtifact from '@graphprotocol/contracts/build/contracts/contracts/rewards/RewardsManager.sol/RewardsManager.json' + +export default buildModule('RewardsManager', (m) => { + const { Controller } = m.useModule(ControllerModule) + + const issuancePerBlock = m.getParameter('issuancePerBlock') + const subgraphAvailabilityOracle = m.getParameter('subgraphAvailabilityOracle') + const subgraphServiceAddress = m.getParameter('subgraphServiceAddress') + + const { instance: RewardsManager } = deployWithGraphProxy(m, { + name: 'RewardsManager', + artifact: RewardsManagerArtifact, + args: [Controller], + }) + + m.call(RewardsManager, 'setSubgraphAvailabilityOracle', [subgraphAvailabilityOracle]) + m.call(RewardsManager, 'setIssuancePerBlock', [issuancePerBlock]) + m.call(RewardsManager, 'setSubgraphService', [subgraphServiceAddress]) + + return { RewardsManager } +}) diff --git a/packages/horizon/ignition/modules/proxy/GraphProxy.ts b/packages/horizon/ignition/modules/proxy/GraphProxy.ts new file mode 100644 index 000000000..85455977f --- /dev/null +++ b/packages/horizon/ignition/modules/proxy/GraphProxy.ts @@ -0,0 +1,36 @@ +import { ArgumentType, Artifact, ContractOptions, IgnitionModuleBuilder } from '@nomicfoundation/ignition-core' + +import GraphProxyAdminModule from '../periphery/GraphProxyAdmin' +import GraphProxyArtifact from '@graphprotocol/contracts/build/contracts/contracts/upgrades/GraphProxy.sol/GraphProxy.json' + +export function deployWithGraphProxy(m: IgnitionModuleBuilder, contract: { name: string, artifact?: Artifact, args?: ArgumentType[] }, options?: ContractOptions) { + const { GraphProxyAdmin } = m.useModule(GraphProxyAdminModule) + + options = options || {} + + // Deploy implementation + let implementation + if (contract.artifact === undefined) { + implementation = m.contract(contract.name, [], options) + } else { + implementation = m.contract(contract.name, contract.artifact, [], options) + } + + // Deploy proxy and initialize + const proxy = m.contract('GraphProxy', GraphProxyArtifact, [implementation, GraphProxyAdmin], options) + if (contract.args === undefined) { + m.call(GraphProxyAdmin, 'acceptProxy', [implementation, proxy], options) + } else { + m.call(GraphProxyAdmin, 'acceptProxyAndCall', [implementation, proxy, m.encodeFunctionCall(implementation, 'initialize', contract.args)], options) + } + + // Load proxy with implementation ABI + let instance + if (contract.artifact === undefined) { + instance = m.contractAt(contract.name, proxy, options) + } else { + instance = m.contractAt(`${contract.name}_Instance`, contract.artifact, proxy, options) + } + + return { proxy, implementation, instance } +} diff --git a/packages/horizon/ignition/modules/proxy/TransparentUpgradeableProxy.ts b/packages/horizon/ignition/modules/proxy/TransparentUpgradeableProxy.ts new file mode 100644 index 000000000..6de1f28ee --- /dev/null +++ b/packages/horizon/ignition/modules/proxy/TransparentUpgradeableProxy.ts @@ -0,0 +1,33 @@ +import { IgnitionModuleBuilder } from '@nomicfoundation/ignition-core' + +import DummyArtifact from '../../../build/contracts/contracts/mocks/Dummy.sol/Dummy.json' +import ProxyAdminArtifact from '@openzeppelin/contracts/build/contracts/ProxyAdmin.json' +import TransparentUpgradeableProxyArtifact from '@openzeppelin/contracts/build/contracts/TransparentUpgradeableProxy.json' + +// Deploy a TransparentUpgradeableProxy +// Note that this module uses a dummy contract as the implementation as the proxy requires a valid contract +// address to be deployed +export function deployWithOZProxy(m: IgnitionModuleBuilder, contractName: string) { + const deployer = m.getAccount(0) + + const dummy = m.contract('Dummy', DummyArtifact, [], { id: `OZProxyDummy_${contractName}` }) + const Proxy = m.contract('TransparentUpgradeableProxy', TransparentUpgradeableProxyArtifact, [ + dummy, + deployer, + '0x', + ], + { id: `TransparentUpgradeableProxy_${contractName}` }) + + const proxyAdminAddress = m.readEventArgument( + Proxy, + 'AdminChanged', + 'newAdmin', + { + id: `TransparentUpgradeableProxy_${contractName}_AdminChanged`, + }, + ) + + const ProxyAdmin = m.contractAt('ProxyAdmin', ProxyAdminArtifact, proxyAdminAddress, { id: `ProxyAdmin_${contractName}` }) + + return { ProxyAdmin, Proxy } +} diff --git a/packages/horizon/package.json b/packages/horizon/package.json index 064e7e1db..4c6624051 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -9,17 +9,20 @@ "lint:sol": "prettier --write contracts/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build cache typechain-types", - "build": "forge build contracts && hardhat compile", - "test": "FOUNDRY_PROFILE=test forge test -vvv && hardhat test" + "build": "forge build && hardhat compile", + "test": "forge test && hardhat test" }, "devDependencies": { "@graphprotocol/contracts": "workspace:^7.0.0", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.8", "@nomicfoundation/hardhat-foundry": "^1.1.1", + "@nomicfoundation/hardhat-ignition": "^0.15.5", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.5", "@nomicfoundation/hardhat-network-helpers": "^1.0.0", "@nomicfoundation/hardhat-toolbox": "^4.0.0", - "@nomicfoundation/hardhat-verify": "^2.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.10", + "@nomicfoundation/ignition-core": "^0.15.5", "@openzeppelin/contracts": "^5.0.2", "@openzeppelin/contracts-upgradeable": "^5.0.2", "@typechain/ethers-v6": "^0.5.0", @@ -30,7 +33,7 @@ "chai": "^4.2.0", "eslint": "^8.56.0", "eslint-graph-config": "workspace:^0.0.1", - "ethers": "^6.4.0", + "ethers": "^6.13.2", "hardhat": "^2.20.1", "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.8", diff --git a/packages/horizon/scripts/deploy.ts b/packages/horizon/scripts/deploy.ts new file mode 100644 index 000000000..a7daff3d4 --- /dev/null +++ b/packages/horizon/scripts/deploy.ts @@ -0,0 +1,16 @@ +import { ignition } from 'hardhat' + +import Parameters from '../ignition/graph.hardhat.json' +import PeripheryModule from '../ignition/modules/periphery' + +async function main() { + await ignition.deploy(PeripheryModule, { + parameters: Parameters, + }) +} + +main() + .catch((error) => { + console.error(error) + process.exit(1) + }) diff --git a/packages/horizon/tsconfig.json b/packages/horizon/tsconfig.json index 143316f16..8de96f814 100644 --- a/packages/horizon/tsconfig.json +++ b/packages/horizon/tsconfig.json @@ -12,6 +12,7 @@ "hardhat.config.ts", "scripts/**/*.ts", "test/**/*.ts", + "ignition/**/*.ts", "eslint.config.js", "prettier.config.js" ] diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts index 17ebc2053..1e2dfc9fd 100644 --- a/packages/subgraph-service/hardhat.config.ts +++ b/packages/subgraph-service/hardhat.config.ts @@ -1,4 +1,5 @@ import '@nomicfoundation/hardhat-foundry' +import '@nomicfoundation/hardhat-ignition-ethers' import '@nomicfoundation/hardhat-toolbox' import 'hardhat-contract-sizer' import 'hardhat-storage-layout' @@ -10,7 +11,6 @@ const config: HardhatUserConfig = { solidity: { version: '0.8.27', settings: { - viaIR: true, optimizer: { enabled: true, runs: 200, diff --git a/packages/subgraph-service/ignition/configs/subgraph-service.hardhat.json b/packages/subgraph-service/ignition/configs/subgraph-service.hardhat.json new file mode 100644 index 000000000..83dfa1899 --- /dev/null +++ b/packages/subgraph-service/ignition/configs/subgraph-service.hardhat.json @@ -0,0 +1,13 @@ +{ + "DisputeManager": { + "arbitrator": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", + "disputePeriod": 2419200, + "disputeDeposit": "10000000000000000000000n", + "fishermanRewardCut": 500000, + "maxSlashingCut": 1000000 + }, + "SubgraphService": { + "minimumProvisionTokens": "100000000000000000000000n", + "maximumDelegationRatio": 16 + } +} diff --git a/packages/subgraph-service/ignition/modules/DisputeManager.ts b/packages/subgraph-service/ignition/modules/DisputeManager.ts new file mode 100644 index 000000000..ff3921eca --- /dev/null +++ b/packages/subgraph-service/ignition/modules/DisputeManager.ts @@ -0,0 +1,36 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import ProxyAdminArtifact from '@openzeppelin/contracts/build/contracts/ProxyAdmin.json' + +// TODO: transfer ownership of ProxyAdmin??? +export default buildModule('DisputeManager', (m) => { + // Parameters - dynamically plugged in by the deploy script + const controllerAddress = m.getParameter('controllerAddress') + const disputeManagerProxyAddress = m.getParameter('disputeManagerProxyAddress') + const disputeManagerProxyAdminAddress = m.getParameter('disputeManagerProxyAdminAddress') + + // Parameters - config file + const arbitrator = m.getParameter('arbitrator') + const disputePeriod = m.getParameter('disputePeriod') + const disputeDeposit = m.getParameter('disputeDeposit') + const fishermanRewardCut = m.getParameter('fishermanRewardCut') + const maxSlashingCut = m.getParameter('maxSlashingCut') + + // Deploy implementation + const DisputeManagerImplementation = m.contract('DisputeManager', [controllerAddress]) + + // Upgrade implementation + const DisputeManagerProxyAdmin = m.contractAt('TransparentUpgradeableProxy', ProxyAdminArtifact, disputeManagerProxyAdminAddress) + const encodedCall = m.encodeFunctionCall(DisputeManagerImplementation, 'initialize', [ + arbitrator, + disputePeriod, + disputeDeposit, + fishermanRewardCut, + maxSlashingCut, + ]) + m.call(DisputeManagerProxyAdmin, 'upgradeAndCall', [disputeManagerProxyAddress, DisputeManagerImplementation, encodedCall]) + + const DisputeManager = m.contractAt('DisputeManager', disputeManagerProxyAddress, { id: 'DisputeManager_Instance' }) + + return { DisputeManager, DisputeManagerImplementation } +}) diff --git a/packages/subgraph-service/ignition/modules/Proxies.ts b/packages/subgraph-service/ignition/modules/Proxies.ts new file mode 100644 index 000000000..3ae5168b4 --- /dev/null +++ b/packages/subgraph-service/ignition/modules/Proxies.ts @@ -0,0 +1,10 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' +import { deployWithOZProxy } from '@graphprotocol/horizon/ignition/modules/proxy/TransparentUpgradeableProxy' + +export default buildModule('SubgraphServiceProxies', (m) => { + // Deploy proxies contracts using OZ TransparentUpgradeableProxy + const { Proxy: DisputeManagerProxy, ProxyAdmin: DisputeManagerProxyAdmin } = deployWithOZProxy(m, 'DisputeManager') + const { Proxy: SubgraphServiceProxy, ProxyAdmin: SubgraphServiceProxyAdmin } = deployWithOZProxy(m, 'SubgraphService') + + return { DisputeManagerProxy, DisputeManagerProxyAdmin, SubgraphServiceProxy, SubgraphServiceProxyAdmin } +}) diff --git a/packages/subgraph-service/ignition/modules/SubgraphService.ts b/packages/subgraph-service/ignition/modules/SubgraphService.ts new file mode 100644 index 000000000..783cd7d15 --- /dev/null +++ b/packages/subgraph-service/ignition/modules/SubgraphService.ts @@ -0,0 +1,34 @@ +/* eslint-disable no-secrets/no-secrets */ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import ProxyAdminArtifact from '@openzeppelin/contracts/build/contracts/ProxyAdmin.json' + +// TODO: transfer ownership of ProxyAdmin??? +export default buildModule('SubgraphService', (m) => { + // Parameters - dynamically plugged in by the deploy script + const controllerAddress = m.getParameter('controllerAddress') + const subgraphServiceProxyAddress = m.getParameter('subgraphServiceProxyAddress') + const subgraphServiceProxyAdminAddress = m.getParameter('subgraphServiceProxyAdminAddress') + const disputeManagerAddress = m.getParameter('disputeManagerAddress') + const tapCollectorAddress = m.getParameter('tapCollectorAddress') + const curationAddress = m.getParameter('curationAddress') + + // Parameters - config file + const minimumProvisionTokens = m.getParameter('minimumProvisionTokens') + const maximumDelegationRatio = m.getParameter('maximumDelegationRatio') + + // Deploy implementation + const SubgraphServiceImplementation = m.contract('SubgraphService', [controllerAddress, disputeManagerAddress, tapCollectorAddress, curationAddress]) + + // Upgrade implementation + const SubgraphServiceProxyAdmin = m.contractAt('TransparentUpgradeableProxy', ProxyAdminArtifact, subgraphServiceProxyAdminAddress) + const encodedCall = m.encodeFunctionCall(SubgraphServiceImplementation, 'initialize', [ + minimumProvisionTokens, + maximumDelegationRatio, + ]) + m.call(SubgraphServiceProxyAdmin, 'upgradeAndCall', [subgraphServiceProxyAddress, SubgraphServiceImplementation, encodedCall]) + + const SubgraphService = m.contractAt('SubgraphService', subgraphServiceProxyAddress, { id: 'SubgraphService_Instance' }) + + return { SubgraphService, SubgraphServiceImplementation } +}) diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index bb5dd9ea9..419d5f160 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -16,11 +16,14 @@ "@graphprotocol/contracts": "workspace:^7.0.0", "@graphprotocol/horizon": "workspace:^0.0.1", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.8", "@nomicfoundation/hardhat-foundry": "^1.1.1", + "@nomicfoundation/hardhat-ignition": "^0.15.5", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.5", "@nomicfoundation/hardhat-network-helpers": "^1.0.0", "@nomicfoundation/hardhat-toolbox": "^4.0.0", - "@nomicfoundation/hardhat-verify": "^2.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.10", + "@nomicfoundation/ignition-core": "^0.15.5", "@openzeppelin/contracts": "^5.0.2", "@openzeppelin/contracts-upgradeable": "^5.0.2", "@typechain/ethers-v6": "^0.5.0", @@ -31,7 +34,7 @@ "chai": "^4.2.0", "eslint": "^8.56.0", "eslint-graph-config": "workspace:^0.0.1", - "ethers": "^6.4.0", + "ethers": "^6.13.2", "hardhat": "^2.20.1", "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.8", diff --git a/packages/subgraph-service/scripts/deploy.ts b/packages/subgraph-service/scripts/deploy.ts index cf87ff10f..17ff2feb2 100644 --- a/packages/subgraph-service/scripts/deploy.ts +++ b/packages/subgraph-service/scripts/deploy.ts @@ -1,28 +1,107 @@ -import { ethers } from 'hardhat' +/* eslint-disable no-prototype-builtins */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { ignition } from 'hardhat' +import DisputeManagerModule from '../ignition/modules/DisputeManager' +import HorizonModule from '@graphprotocol/horizon/ignition/modules/horizon' +import SubgraphServiceModule from '../ignition/modules/SubgraphService' +import SubgraphServiceProxiesModule from '../ignition/modules/Proxies' + +// Horizon needs the SubgraphService proxy address before it can be deployed +// But SubgraphService and DisputeManager implementations need Horizon... +// So the deployment order is: +// - Deploy SubgraphService and DisputeManager proxies +// - Deploy Horizon +// - Deploy SubgraphService and DisputeManager implementations async function main() { - const currentTimestampInSeconds = Math.round(Date.now() / 1000) - const unlockTime = currentTimestampInSeconds + 60 - - const lockedAmount = ethers.parseEther('0.001') - const a = 1 - console.log(a) - const lock = await ethers.deployContract('Lock', [unlockTime], { - value: lockedAmount, + // TODO: Dynamically load config file based on the hardhat --network value + const HorizonConfig = removeNFromBigInts(require('@graphprotocol/horizon/ignition/configs/horizon.hardhat.json')) + const SubgraphServiceConfig = removeNFromBigInts(require('../ignition/configs/subgraph-service.hardhat.json')) + + // Deploy proxies + const { DisputeManagerProxy, DisputeManagerProxyAdmin, SubgraphServiceProxy, SubgraphServiceProxyAdmin } = await ignition.deploy(SubgraphServiceProxiesModule) + + // Deploy Horizon + const { Controller, TAPCollector, Curation } = await ignition.deploy(HorizonModule, { + parameters: patchSubgraphServiceAddress(HorizonConfig, SubgraphServiceProxy.target as string), }) - await lock.waitForDeployment() + // Deploy DisputeManager implementation + await ignition.deploy(DisputeManagerModule, { + parameters: deepMerge(SubgraphServiceConfig, { + DisputeManager: { + controllerAddress: Controller.target as string, + disputeManagerProxyAddress: DisputeManagerProxy.target as string, + disputeManagerProxyAdminAddress: DisputeManagerProxyAdmin.target as string, + }, + }), + }) - console.log( - `Lock with ${ethers.formatEther( - lockedAmount, - )}ETH and unlock timestamp ${unlockTime} deployed to ${typeof lock.target == 'string' ? lock.target : ''}`, - ) + // Deploy SubgraphService implementation + await ignition.deploy(SubgraphServiceModule, { + parameters: deepMerge(SubgraphServiceConfig, { + SubgraphService: { + controllerAddress: Controller.target as string, + subgraphServiceProxyAddress: SubgraphServiceProxy.target as string, + subgraphServiceProxyAdminAddress: SubgraphServiceProxyAdmin.target as string, + disputeManagerAddress: DisputeManagerProxy.target as string, + tapCollectorAddress: TAPCollector.target as string, + curationAddress: Curation.target as string, + }, + }), + }) } - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. main().catch((error) => { console.error(error) - process.exitCode = 1 + process.exit(1) }) + +// -- Auxiliary functions - by GPT -- +function patchSubgraphServiceAddress(jsonData: any, newAddress: string) { + function recursivePatch(obj: any) { + if (typeof obj === 'object' && obj !== null) { + for (const key in obj) { + if (key === 'subgraphServiceAddress') { + obj[key] = newAddress + } else { + recursivePatch(obj[key]) + } + } + } + } + + recursivePatch(jsonData) + return jsonData +} + +function removeNFromBigInts(obj: any): any { + // Ignition requires "n" suffix for bigints, but not here + if (typeof obj === 'string') { + return obj.replace(/(\d+)n/g, '$1') + } else if (Array.isArray(obj)) { + return obj.map(removeNFromBigInts) + } else if (typeof obj === 'object' && obj !== null) { + for (const key in obj) { + obj[key] = removeNFromBigInts(obj[key]) + } + } + return obj +} + +function deepMerge(obj1: any, obj2: any) { + const merged = { ...obj1 } + + for (const key in obj2) { + if (obj2.hasOwnProperty(key)) { + if (typeof obj2[key] === 'object' && obj2[key] !== null && obj1[key]) { + merged[key] = deepMerge(obj1[key], obj2[key]) + } else { + merged[key] = obj2[key] + } + } + } + + return merged +} diff --git a/packages/subgraph-service/tsconfig.json b/packages/subgraph-service/tsconfig.json index adee669ce..8de96f814 100644 --- a/packages/subgraph-service/tsconfig.json +++ b/packages/subgraph-service/tsconfig.json @@ -10,9 +10,10 @@ }, "include": [ "hardhat.config.ts", - "prettier.config.js", "scripts/**/*.ts", "test/**/*.ts", - "eslint.config.js" + "ignition/**/*.ts", + "eslint.config.js", + "prettier.config.js" ] } diff --git a/yarn.lock b/yarn.lock index 4d5746433..4cfd396f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1843,6 +1843,19 @@ __metadata: languageName: node linkType: hard +"@ethersproject/address@npm:5.6.1": + version: 5.6.1 + resolution: "@ethersproject/address@npm:5.6.1" + dependencies: + "@ethersproject/bignumber": "npm:^5.6.2" + "@ethersproject/bytes": "npm:^5.6.1" + "@ethersproject/keccak256": "npm:^5.6.1" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/rlp": "npm:^5.6.1" + checksum: 7ac29a0abcb9970c6f5f9a2d2e8247d3c433ee9a022861cbf4f8d437f095a5293f3d323b8ec3433df622364071232b227248f1ac04c4ddea353bf18e2e4d76cf + languageName: node + linkType: hard + "@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:>=5.0.0-beta.128, @ethersproject/address@npm:^5.0.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.0.8, @ethersproject/address@npm:^5.6.0, @ethersproject/address@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" @@ -1905,7 +1918,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:>=5.0.0-beta.130, @ethersproject/bignumber@npm:^5.0.0, @ethersproject/bignumber@npm:^5.1.1, @ethersproject/bignumber@npm:^5.6.0, @ethersproject/bignumber@npm:^5.7.0": +"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:>=5.0.0-beta.130, @ethersproject/bignumber@npm:^5.0.0, @ethersproject/bignumber@npm:^5.1.1, @ethersproject/bignumber@npm:^5.6.0, @ethersproject/bignumber@npm:^5.6.2, @ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" dependencies: @@ -1925,7 +1938,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:>=5.0.0-beta.129, @ethersproject/bytes@npm:^5.0.0, @ethersproject/bytes@npm:^5.0.8, @ethersproject/bytes@npm:^5.6.0, @ethersproject/bytes@npm:^5.7.0": +"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:>=5.0.0-beta.129, @ethersproject/bytes@npm:^5.0.0, @ethersproject/bytes@npm:^5.0.8, @ethersproject/bytes@npm:^5.6.0, @ethersproject/bytes@npm:^5.6.1, @ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" dependencies: @@ -2124,7 +2137,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:>=5.0.0-beta.127, @ethersproject/keccak256@npm:^5.6.0, @ethersproject/keccak256@npm:^5.7.0": +"@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:>=5.0.0-beta.127, @ethersproject/keccak256@npm:^5.6.0, @ethersproject/keccak256@npm:^5.6.1, @ethersproject/keccak256@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/keccak256@npm:5.7.0" dependencies: @@ -2326,7 +2339,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.6.0, @ethersproject/rlp@npm:^5.7.0": +"@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.6.0, @ethersproject/rlp@npm:^5.6.1, @ethersproject/rlp@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/rlp@npm:5.7.0" dependencies: @@ -2918,11 +2931,14 @@ __metadata: dependencies: "@graphprotocol/contracts": "workspace:^7.0.0" "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.0" - "@nomicfoundation/hardhat-ethers": "npm:^3.0.0" + "@nomicfoundation/hardhat-ethers": "npm:^3.0.8" "@nomicfoundation/hardhat-foundry": "npm:^1.1.1" + "@nomicfoundation/hardhat-ignition": "npm:^0.15.5" + "@nomicfoundation/hardhat-ignition-ethers": "npm:^0.15.5" "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0" "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" - "@nomicfoundation/hardhat-verify": "npm:^2.0.0" + "@nomicfoundation/hardhat-verify": "npm:^2.0.10" + "@nomicfoundation/ignition-core": "npm:^0.15.5" "@openzeppelin/contracts": "npm:^5.0.2" "@openzeppelin/contracts-upgradeable": "npm:^5.0.2" "@typechain/ethers-v6": "npm:^0.5.0" @@ -2933,7 +2949,7 @@ __metadata: chai: "npm:^4.2.0" eslint: "npm:^8.56.0" eslint-graph-config: "workspace:^0.0.1" - ethers: "npm:^6.4.0" + ethers: "npm:^6.13.2" hardhat: "npm:^2.20.1" hardhat-contract-sizer: "npm:^2.10.0" hardhat-gas-reporter: "npm:^1.0.8" @@ -3008,11 +3024,14 @@ __metadata: "@graphprotocol/contracts": "workspace:^7.0.0" "@graphprotocol/horizon": "workspace:^0.0.1" "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.0" - "@nomicfoundation/hardhat-ethers": "npm:^3.0.0" + "@nomicfoundation/hardhat-ethers": "npm:^3.0.8" "@nomicfoundation/hardhat-foundry": "npm:^1.1.1" + "@nomicfoundation/hardhat-ignition": "npm:^0.15.5" + "@nomicfoundation/hardhat-ignition-ethers": "npm:^0.15.5" "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.0" "@nomicfoundation/hardhat-toolbox": "npm:^4.0.0" - "@nomicfoundation/hardhat-verify": "npm:^2.0.0" + "@nomicfoundation/hardhat-verify": "npm:^2.0.10" + "@nomicfoundation/ignition-core": "npm:^0.15.5" "@openzeppelin/contracts": "npm:^5.0.2" "@openzeppelin/contracts-upgradeable": "npm:^5.0.2" "@typechain/ethers-v6": "npm:^0.5.0" @@ -3023,7 +3042,7 @@ __metadata: chai: "npm:^4.2.0" eslint: "npm:^8.56.0" eslint-graph-config: "workspace:^0.0.1" - ethers: "npm:^6.4.0" + ethers: "npm:^6.13.2" hardhat: "npm:^2.20.1" hardhat-contract-sizer: "npm:^2.10.0" hardhat-gas-reporter: "npm:^1.0.8" @@ -4634,16 +4653,16 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/hardhat-ethers@npm:^3.0.0": - version: 3.0.6 - resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.6" +"@nomicfoundation/hardhat-ethers@npm:^3.0.8": + version: 3.0.8 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.8" dependencies: debug: "npm:^4.1.1" lodash.isequal: "npm:^4.5.0" peerDependencies: ethers: ^6.1.0 hardhat: ^2.0.0 - checksum: c7abe4234fae6422a357ef9e959cfe4183d5d7121d18e9f71b1659944419fde7d2a0290cd42fd5e85d855d8c83b86bbaed316f4950f0976015f941d958679a99 + checksum: 478b5d9607e7fc50377bec45ecebbf74240719c76aa08c81052d2a2174eee6f422db8cfd3f13fd17a080d8ff1046fac50dfffa3a2e57c9e3ed466932239e4af2 languageName: node linkType: hard @@ -4658,6 +4677,36 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/hardhat-ignition-ethers@npm:^0.15.5": + version: 0.15.5 + resolution: "@nomicfoundation/hardhat-ignition-ethers@npm:0.15.5" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.4 + "@nomicfoundation/hardhat-ignition": ^0.15.5 + "@nomicfoundation/ignition-core": ^0.15.5 + ethers: ^6.7.0 + hardhat: ^2.18.0 + checksum: 19f0e029a580dd4d27048f1e87f8111532684cf7f0a2b5c8d6ae8d811ff489629305e3a616cb89702421142c7c628f1efa389781414de1279689018c463cce60 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-ignition@npm:^0.15.5": + version: 0.15.5 + resolution: "@nomicfoundation/hardhat-ignition@npm:0.15.5" + dependencies: + "@nomicfoundation/ignition-core": "npm:^0.15.5" + "@nomicfoundation/ignition-ui": "npm:^0.15.5" + chalk: "npm:^4.0.0" + debug: "npm:^4.3.2" + fs-extra: "npm:^10.0.0" + prompts: "npm:^2.4.2" + peerDependencies: + "@nomicfoundation/hardhat-verify": ^2.0.1 + hardhat: ^2.18.0 + checksum: b3d9755f2bf89157b6ae0cb6cebea264f76f556ae0b3fc5a62afb5e0f6ed70b3d82d8f692b1c49b2ef2d60cdb45ee28fb148cfca1aa5a53bfe37772c71e75a08 + languageName: node + linkType: hard + "@nomicfoundation/hardhat-network-helpers@npm:^1.0.0, @nomicfoundation/hardhat-network-helpers@npm:^1.0.9": version: 1.0.10 resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.0.10" @@ -4694,9 +4743,9 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/hardhat-verify@npm:^2.0.0": - version: 2.0.7 - resolution: "@nomicfoundation/hardhat-verify@npm:2.0.7" +"@nomicfoundation/hardhat-verify@npm:^2.0.10": + version: 2.0.10 + resolution: "@nomicfoundation/hardhat-verify@npm:2.0.10" dependencies: "@ethersproject/abi": "npm:^5.1.2" "@ethersproject/address": "npm:^5.0.2" @@ -4709,7 +4758,31 @@ __metadata: undici: "npm:^5.14.0" peerDependencies: hardhat: ^2.0.4 - checksum: a6b3b89d3d2a594c44b50832840deefd3261b158bde774319322859077637f656c2e436af21ca3ce10d60eac78e3a1fbfea02abfe20a4729f97b4f30515524a6 + checksum: c5b8e214f2dcdda0530dbb338f65e01bbb6e6b0f96930a88c01b1d1cf2def3f470e0bdb362807bb9a7dbe8216f937b55d14ab251d3cccd2208d6b60cebf2c358 + languageName: node + linkType: hard + +"@nomicfoundation/ignition-core@npm:^0.15.5": + version: 0.15.5 + resolution: "@nomicfoundation/ignition-core@npm:0.15.5" + dependencies: + "@ethersproject/address": "npm:5.6.1" + "@nomicfoundation/solidity-analyzer": "npm:^0.1.1" + cbor: "npm:^9.0.0" + debug: "npm:^4.3.2" + ethers: "npm:^6.7.0" + fs-extra: "npm:^10.0.0" + immer: "npm:10.0.2" + lodash: "npm:4.17.21" + ndjson: "npm:2.0.0" + checksum: ff14724d8e992dc54291da6e6a864f6b3db268b6725d0af6ecbf3f81ed65f6824441421b23129d118cd772efc8ab0275d1decf203019cb3049a48b37f9c15432 + languageName: node + linkType: hard + +"@nomicfoundation/ignition-ui@npm:^0.15.5": + version: 0.15.5 + resolution: "@nomicfoundation/ignition-ui@npm:0.15.5" + checksum: 7d10e30c3078731e4feb91bd7959dfb5a0eeac6f34f6261fada2bf330ff8057ecd576ce0fb3fe856867af2d7c67f31bd75a896110b58d93ff3f27f04f6771278 languageName: node linkType: hard @@ -4720,6 +4793,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2" + checksum: ef3b13bb2133fea6621db98f991036a3a84d2b240160edec50beafa6ce821fe2f0f5cd4aa61adb9685aff60cd0425982ffd15e0b868b7c768e90e26b8135b825 + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.1" @@ -4727,6 +4807,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.2" + checksum: 3cb6a00cd200b94efd6f59ed626c705c6f773b92ccf8b90471285cd0e81b35f01edb30c1aa5a4633393c2adb8f20fd34e90c51990dc4e30658e8a67c026d16c9 + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-freebsd-x64@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-freebsd-x64@npm:0.1.1" @@ -4741,6 +4828,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.2" + checksum: cb9725e7bdc3ba9c1feaef96dbf831c1a59c700ca633a9929fd97debdcb5ce06b5d7b4e6dbc076279978707214d01e2cd126d8e3f4cabc5c16525c031a47b95c + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.1" @@ -4748,6 +4842,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.2" + checksum: 82a90b1d09ad266ddc510ece2e397f51fdaf29abf7263d2a3a85accddcba2ac24cceb670a3120800611cdcc552eed04919d071e259fdda7564818359ed541f5d + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.1" @@ -4755,6 +4856,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.2" + checksum: d1f20d4d55683bd041ead957e5461b2e43a39e959f905e8866de1d65f8d96118e9b861e994604d9002cb7f056be0844e36c241a6bb531c336b399609977c0998 + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.1" @@ -4762,6 +4870,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.2" + checksum: 6c17f9af3aaf184c0a217cf723076051c502d85e731dbc97f34b838f9ae1b597577abac54a2af49b3fd986b09131c52fa21fd5393b22d05e1ec7fee96a8249c2 + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-win32-arm64-msvc@npm:0.1.1" @@ -4783,6 +4898,13 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.2" + checksum: da198464f5ee0d19b6decdfaa65ee0df3097b8960b8483bb7080931968815a5d60f27191229d47a198955784d763d5996f0b92bfde3551612ad972c160b0b000 + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer@npm:^0.1.0": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer@npm:0.1.1" @@ -4822,6 +4944,36 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/solidity-analyzer@npm:^0.1.1": + version: 0.1.2 + resolution: "@nomicfoundation/solidity-analyzer@npm:0.1.2" + dependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-darwin-x64": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "npm:0.1.2" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "npm:0.1.2" + dependenciesMeta: + "@nomicfoundation/solidity-analyzer-darwin-arm64": + optional: true + "@nomicfoundation/solidity-analyzer-darwin-x64": + optional: true + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": + optional: true + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": + optional: true + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": + optional: true + "@nomicfoundation/solidity-analyzer-linux-x64-musl": + optional: true + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": + optional: true + checksum: e4f503e9287e18967535af669ca7e26e2682203c45a34ea85da53122da1dee1278f2b8c76c20c67fadd7c1b1a98eeecffd2cbc136860665e3afa133817c0de54 + languageName: node + linkType: hard + "@nomiclabs/hardhat-ethers@npm:^2.0.0, @nomiclabs/hardhat-ethers@npm:^2.0.2, @nomiclabs/hardhat-ethers@npm:^2.1.1, @nomiclabs/hardhat-ethers@npm:^2.2.3": version: 2.2.3 resolution: "@nomiclabs/hardhat-ethers@npm:2.2.3" @@ -12084,9 +12236,9 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^6.4.0": - version: 6.12.1 - resolution: "ethers@npm:6.12.1" +"ethers@npm:^6.13.2, ethers@npm:^6.7.0": + version: 6.13.2 + resolution: "ethers@npm:6.13.2" dependencies: "@adraffy/ens-normalize": "npm:1.10.1" "@noble/curves": "npm:1.2.0" @@ -12094,8 +12246,8 @@ __metadata: "@types/node": "npm:18.15.13" aes-js: "npm:4.0.0-beta.5" tslib: "npm:2.4.0" - ws: "npm:8.5.0" - checksum: 7686e1efdb0a831578f35d69188783c225de5a6fbb1b422327bc45cee04d49a2707e73c9342a6a5eb2870ce35668c71372737439ec3993d31d83f4a0e2446cc7 + ws: "npm:8.17.1" + checksum: 5956389a180992f8b6d90bc21b2e0f28619a098513d3aeb7a350a0b7c5852d635a9d7fd4ced1af50c985dd88398716f66dfd4a2de96c5c3a67150b93543d92af languageName: node linkType: hard @@ -14774,6 +14926,13 @@ __metadata: languageName: node linkType: hard +"immer@npm:10.0.2": + version: 10.0.2 + resolution: "immer@npm:10.0.2" + checksum: b6c23538cd174a4cadd6f8d92bf0245e2c2a7bdabbd3200a08f1e99bb52e463fb552bb2d025ddd45f4e335390f8bd307e2c813e54a004dd651fe1ec161674e42 + languageName: node + linkType: hard + "immutable@npm:^4.0.0-rc.12": version: 4.3.6 resolution: "immutable@npm:4.3.6" @@ -16208,7 +16367,7 @@ __metadata: languageName: node linkType: hard -"json-stringify-safe@npm:~5.0.1": +"json-stringify-safe@npm:^5.0.1, json-stringify-safe@npm:~5.0.1": version: 5.0.1 resolution: "json-stringify-safe@npm:5.0.1" checksum: 7dbf35cd0411d1d648dceb6d59ce5857ec939e52e4afc37601aa3da611f0987d5cee5b38d58329ceddf3ed48bd7215229c8d52059ab01f2444a338bf24ed0f37 @@ -17008,7 +17167,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.14.2, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:~4.17.0": +"lodash@npm:4.17.21, lodash@npm:^4.14.2, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:~4.17.0": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c @@ -18287,6 +18446,21 @@ __metadata: languageName: node linkType: hard +"ndjson@npm:2.0.0": + version: 2.0.0 + resolution: "ndjson@npm:2.0.0" + dependencies: + json-stringify-safe: "npm:^5.0.1" + minimist: "npm:^1.2.5" + readable-stream: "npm:^3.6.0" + split2: "npm:^3.0.0" + through2: "npm:^4.0.0" + bin: + ndjson: cli.js + checksum: b7f3de5e12e0466cfa3688a3ba6cedec0ab54bd821f1b16926c9ef7017983b131832430061d25dfcb635f65a254b535681eca213c6feb5d1958bee8d35a04cc9 + languageName: node + linkType: hard + "negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" @@ -25472,18 +25646,18 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.5.0": - version: 8.5.0 - resolution: "ws@npm:8.5.0" +"ws@npm:8.17.1": + version: 8.17.1 + resolution: "ws@npm:8.17.1" peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - checksum: 0baeee03e97865accda8fad51e8e5fa17d19b8e264529efdf662bbba2acc1c7f1de8316287e6df5cb639231a96009e6d5234b57e6ff36ee2d04e49a0995fec2f + checksum: f4a49064afae4500be772abdc2211c8518f39e1c959640457dcee15d4488628620625c783902a52af2dd02f68558da2868fd06e6fd0e67ebcd09e6881b1b5bfe languageName: node linkType: hard From 2f3a5e0d96cf0a2b780f2816149587ff9dc1f9bb Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Wed, 2 Oct 2024 06:45:53 +1000 Subject: [PATCH 250/277] chore(Horizon): reprovision only tokens thawed (#1046) * chore(Horizon): reprovision only tokens thawed * fix: rename variable --- .../internal/IHorizonStakingMain.sol | 3 +- .../contracts/staking/HorizonStaking.sol | 22 +++++---- .../HorizonStakingShared.t.sol | 9 ++-- .../test/staking/provision/reprovision.t.sol | 48 ++----------------- 4 files changed, 22 insertions(+), 60 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index eafce457a..6e0cc024f 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -614,13 +614,12 @@ interface IHorizonStakingMain { * @param serviceProvider The service provider address * @param oldVerifier The verifier address for which the tokens are currently provisioned * @param newVerifier The verifier address for which the tokens will be provisioned - * @param tokens The amount of tokens to move + * @param nThawRequests The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests. */ function reprovision( address serviceProvider, address oldVerifier, address newVerifier, - uint256 tokens, uint256 nThawRequests ) external; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 982e06ae0..f49a3e566 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -209,7 +209,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address serviceProvider, address oldVerifier, address newVerifier, - uint256 tokens, uint256 nThawRequests ) external @@ -218,8 +217,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { onlyAuthorized(serviceProvider, oldVerifier) onlyAuthorized(serviceProvider, newVerifier) { - _deprovision(serviceProvider, oldVerifier, nThawRequests); - _addToProvision(serviceProvider, newVerifier, tokens); + uint256 tokensThawed = _deprovision(serviceProvider, oldVerifier, nThawRequests); + _addToProvision(serviceProvider, newVerifier, tokensThawed); } /** @@ -695,13 +694,17 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice See {IHorizonStakingMain-deprovision}. */ - function _deprovision(address _serviceProvider, address _verifier, uint256 _nThawRequests) private { + function _deprovision( + address _serviceProvider, + address _verifier, + uint256 _nThawRequests + ) private returns (uint256 tokensThawed) { Provision storage prov = _provisions[_serviceProvider][_verifier]; - uint256 tokensThawed = 0; + uint256 tokensThawed_ = 0; uint256 sharesThawing = prov.sharesThawing; uint256 tokensThawing = prov.tokensThawing; - (tokensThawed, tokensThawing, sharesThawing) = _fulfillThawRequests( + (tokensThawed_, tokensThawing, sharesThawing) = _fulfillThawRequests( _serviceProvider, _verifier, _serviceProvider, @@ -710,12 +713,13 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _nThawRequests ); - prov.tokens = prov.tokens - tokensThawed; + prov.tokens = prov.tokens - tokensThawed_; prov.sharesThawing = sharesThawing; prov.tokensThawing = tokensThawing; - _serviceProviders[_serviceProvider].tokensProvisioned -= tokensThawed; + _serviceProviders[_serviceProvider].tokensProvisioned -= tokensThawed_; - emit TokensDeprovisioned(_serviceProvider, _verifier, tokensThawed); + emit TokensDeprovisioned(_serviceProvider, _verifier, tokensThawed_); + return tokensThawed_; } /** diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index d9f300979..e171e455e 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -559,7 +559,6 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { address serviceProvider, address verifier, address newVerifier, - uint256 tokens, uint256 nThawRequests ) internal { // before @@ -595,8 +594,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { vm.expectEmit(address(staking)); emit IHorizonStakingMain.TokensDeprovisioned(serviceProvider, verifier, calcValues.tokensThawed); vm.expectEmit(); - emit IHorizonStakingMain.ProvisionIncreased(serviceProvider, newVerifier, tokens); - staking.reprovision(serviceProvider, verifier, newVerifier, tokens, nThawRequests); + emit IHorizonStakingMain.ProvisionIncreased(serviceProvider, newVerifier, calcValues.tokensThawed); + staking.reprovision(serviceProvider, verifier, newVerifier, nThawRequests); // after Provision memory afterProvision = staking.getProvision(serviceProvider, verifier); @@ -619,7 +618,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.thawingPeriodPending, beforeValues.provision.thawingPeriodPending); // assert: provision new verifier - assertEq(afterProvisionNewVerifier.tokens, beforeValues.provisionNewVerifier.tokens + tokens); + assertEq(afterProvisionNewVerifier.tokens, beforeValues.provisionNewVerifier.tokens + calcValues.tokensThawed); assertEq(afterProvisionNewVerifier.tokensThawing, beforeValues.provisionNewVerifier.tokensThawing); assertEq(afterProvisionNewVerifier.sharesThawing, beforeValues.provisionNewVerifier.sharesThawing); assertEq(afterProvisionNewVerifier.maxVerifierCut, beforeValues.provisionNewVerifier.maxVerifierCut); @@ -632,7 +631,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterServiceProvider.tokensStaked, beforeValues.serviceProvider.tokensStaked); assertEq( afterServiceProvider.tokensProvisioned, - beforeValues.serviceProvider.tokensProvisioned + tokens - calcValues.tokensThawed + beforeValues.serviceProvider.tokensProvisioned + calcValues.tokensThawed - calcValues.tokensThawed ); assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeValues.serviceProvider.__DEPRECATED_tokensAllocated); assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeValues.serviceProvider.__DEPRECATED_tokensLocked); diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 6fd170e4b..722ecfe59 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -25,29 +25,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); - _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); - } - - function testReprovision_TokensOverThawingTokens() public useIndexer { - uint64 thawingPeriod = 1 days; - - // create provision A, thaw 10 ether, skip time so they are fully thawed - _createProvision(users.indexer, subgraphDataServiceAddress, 100 ether, 0, thawingPeriod); - _thaw(users.indexer, subgraphDataServiceAddress, 10 ether); - skip(thawingPeriod + 1); - - // create provision B - _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); - - // reprovision 100 ether from A to B - // this should revert because there are only 10 ether that thawed and the service provider - // doesn't have additional idle stake to cover the difference - vm.expectRevert(); - staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 100 ether, 0); - - // now add some idle stake and try again, it should not revert - _stake(100 ether); - _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 100 ether, 0); + _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 0); } function testReprovision_OperatorMovingTokens( @@ -64,7 +42,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { // Switch back to operator vm.startPrank(users.operator); _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); - _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); + _reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 0); } function testReprovision_RevertWhen_OperatorNotAuthorizedForNewDataService( @@ -85,30 +63,12 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { newDataService ); vm.expectRevert(expectedError); - staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 0); } function testReprovision_RevertWhen_NoThawingTokens(uint256 amount) public useIndexer useProvision(amount, 0, 0) { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, amount, 0); - } - - function testReprovision_RevertWhen_StillThawing( - uint64 thawingPeriod, - uint256 provisionAmount - ) public useIndexer useProvision(provisionAmount, 0, thawingPeriod) { - vm.assume(thawingPeriod > 0); - _thaw(users.indexer, subgraphDataServiceAddress, provisionAmount); - - _createProvision(users.indexer, newDataService, 1 ether, 0, thawingPeriod); - - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientIdleStake(uint256,uint256)", - provisionAmount, - 0 - ); - vm.expectRevert(expectedError); - staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, provisionAmount, 0); + staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 0); } } From fe9d605a0e14dbb4fc519f3ab1c7a8674b7868f6 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Wed, 2 Oct 2024 06:46:17 +1000 Subject: [PATCH 251/277] chore(SubgraphService): allow force closing over allocated allocations (#1044) * chore(SubgraphService): allow force closing over allocated allocations * fix: merge close stale and over allocated functions * fix: removed unused error and fixed natspec for new error --- .../contracts/SubgraphService.sol | 23 +++++-- .../contracts/interfaces/ISubgraphService.sol | 31 +++++++--- .../contracts/utilities/AllocationManager.sol | 12 +++- .../subgraphService/SubgraphService.t.sol | 4 +- .../{closeStale.t.sol => forceClose.t.sol} | 60 ++++++++++++++----- .../collect/indexing/indexing.t.sol | 2 +- 6 files changed, 101 insertions(+), 31 deletions(-) rename packages/subgraph-service/test/subgraphService/allocation/{closeStale.t.sol => forceClose.t.sol} (63%) diff --git a/packages/subgraph-service/contracts/SubgraphService.sol b/packages/subgraph-service/contracts/SubgraphService.sol index 39b12a4c9..58c730f4d 100644 --- a/packages/subgraph-service/contracts/SubgraphService.sol +++ b/packages/subgraph-service/contracts/SubgraphService.sol @@ -312,12 +312,11 @@ contract SubgraphService is /** * @notice See {ISubgraphService.closeStaleAllocation} */ - function closeStaleAllocation(address allocationId) external override { + function forceCloseAllocation(address allocationId) external override { Allocation.State memory allocation = allocations.get(allocationId); - require( - allocation.isStale(maxPOIStaleness), - SubgraphServiceAllocationNotStale(allocationId, allocation.lastPOIPresentedAt) - ); + bool isStale = allocation.isStale(maxPOIStaleness); + bool isOverAllocated_ = _isOverAllocated(allocation.indexer, delegationRatio); + require(isStale || isOverAllocated_, SubgraphServiceCannotForceCloseAllocation(allocationId)); require(!allocation.isAltruistic(), SubgraphServiceAllocationIsAltruistic(allocationId)); _closeAllocation(allocationId); } @@ -476,6 +475,20 @@ contract SubgraphService is return _encodeAllocationProof(indexer, allocationId); } + /** + * @notice See {ISubgraphService.isStaleAllocation} + */ + function isStaleAllocation(address allocationId) external view override returns (bool) { + return allocations.get(allocationId).isStale(maxPOIStaleness); + } + + /** + * @notice See {ISubgraphService.isOverAllocated} + */ + function isOverAllocated(address indexer) external view override returns (bool) { + return _isOverAllocated(indexer, delegationRatio); + } + // -- Data service parameter getters -- /** * @notice Getter for the accepted thawing period range for provisions diff --git a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol index b83d672f7..32ea9e8fb 100644 --- a/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol +++ b/packages/subgraph-service/contracts/interfaces/ISubgraphService.sol @@ -110,11 +110,10 @@ interface ISubgraphService is IDataServiceFees { error SubgraphServiceInvalidRAV(address ravIndexer, address allocationIndexer); /** - * @notice Thrown when trying to force close an allocation that is not stale + * @notice Thrown when trying to force close an allocation that is not stale and the indexer is not over-allocated * @param allocationId The id of the allocation - * @param lastPOIPresentedAt The timestamp when the last POI was presented */ - error SubgraphServiceAllocationNotStale(address allocationId, uint256 lastPOIPresentedAt); + error SubgraphServiceCannotForceCloseAllocation(address allocationId); /** * @notice Thrown when trying to force close an altruistic allocation @@ -128,20 +127,22 @@ interface ISubgraphService is IDataServiceFees { error SubgraphServiceInvalidZeroStakeToFeesRatio(); /** - * @notice Close a stale allocation - * @dev This function can be permissionlessly called when the allocation is stale. - * This ensures rewards for other allocations are not diluted by an inactive allocation + * @notice Force close an allocation + * @dev This function can be permissionlessly called when the allocation is stale or + * if the indexer is over-allocated. This ensures that rewards for other allocations are + * not diluted by an inactive allocation, and that over-allocated indexers stop accumulating + * rewards with tokens they no longer have allocated. * * Requirements: * - Allocation must exist and be open - * - Allocation must be stale + * - Allocation must be stale or indexer must be over-allocated * - Allocation cannot be altruistic * * Emits a {AllocationClosed} event. * * @param allocationId The id of the allocation */ - function closeStaleAllocation(address allocationId) external; + function forceCloseAllocation(address allocationId) external; /** * @notice Change the amount of tokens in an allocation @@ -237,4 +238,18 @@ interface ISubgraphService is IDataServiceFees { * @param allocationId The id of the allocation */ function encodeAllocationProof(address indexer, address allocationId) external view returns (bytes32); + + /** + * @notice Checks if an allocation is stale + * @param allocationId The id of the allocation + * @return True if the allocation is stale, false otherwise + */ + function isStaleAllocation(address allocationId) external view returns (bool); + + /** + * @notice Checks if an indexer is over-allocated + * @param allocationId The id of the allocation + * @return True if the indexer is over-allocated, false otherwise + */ + function isOverAllocated(address allocationId) external view returns (bool); } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 97c3adf99..3d66224c3 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -322,7 +322,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca ); // Check if the indexer is over-allocated and close the allocation if necessary - if (!allocationProvisionTracker.check(_graphStaking(), allocation.indexer, _delegationRatio)) { + if (_isOverAllocated(allocation.indexer, _delegationRatio)) { _closeAllocation(_allocationId); } @@ -479,4 +479,14 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca function _encodeAllocationProof(address _indexer, address _allocationId) internal view returns (bytes32) { return _hashTypedDataV4(keccak256(abi.encode(EIP712_ALLOCATION_PROOF_TYPEHASH, _indexer, _allocationId))); } + + /** + * @notice Checks if an allocation is over-allocated + * @param _indexer The address of the indexer + * @param _delegationRatio The delegation ratio to consider when locking tokens + * @return True if the allocation is over-allocated, false otherwise + */ + function _isOverAllocated(address _indexer, uint32 _delegationRatio) internal view returns (bool) { + return !allocationProvisionTracker.check(_graphStaking(), _indexer, _delegationRatio); + } } diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index e62ce8211..f48235d48 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -151,7 +151,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { assertEq(afterSubgraphAllocatedTokens, _tokens); } - function _closeStaleAllocation(address _allocationId) internal { + function _forceCloseAllocation(address _allocationId) internal { assertTrue(subgraphService.isActiveAllocation(_allocationId)); Allocation.State memory allocation = subgraphService.getAllocation(_allocationId); @@ -168,7 +168,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { ); // close stale allocation - subgraphService.closeStaleAllocation(_allocationId); + subgraphService.forceCloseAllocation(_allocationId); // update allocation allocation = subgraphService.getAllocation(_allocationId); diff --git a/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol b/packages/subgraph-service/test/subgraphService/allocation/forceClose.t.sol similarity index 63% rename from packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol rename to packages/subgraph-service/test/subgraphService/allocation/forceClose.t.sol index 68d736261..8817355f6 100644 --- a/packages/subgraph-service/test/subgraphService/allocation/closeStale.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/forceClose.t.sol @@ -14,7 +14,7 @@ import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol"; import { SubgraphServiceTest } from "../SubgraphService.t.sol"; -contract SubgraphServiceAllocationCloseStaleTest is SubgraphServiceTest { +contract SubgraphServiceAllocationForceCloseTest is SubgraphServiceTest { address private permissionlessBob = makeAddr("permissionlessBob"); @@ -22,17 +22,17 @@ contract SubgraphServiceAllocationCloseStaleTest is SubgraphServiceTest { * TESTS */ - function test_SubgraphService_Allocation_CloseStale( + function test_SubgraphService_Allocation_ForceClose_Stale( uint256 tokens - ) public useIndexer useAllocation(tokens) { - // Skip forward + ) public useIndexer useAllocation(tokens) { + // Skip forward skip(maxPOIStaleness + 1); resetPrank(permissionlessBob); - _closeStaleAllocation(allocationID); + _forceCloseAllocation(allocationID); } - function test_SubgraphService_Allocation_CloseStale_AfterCollecting( + function test_SubgraphService_Allocation_ForceClose_Stale_AfterCollecting( uint256 tokens ) public useIndexer useAllocation(tokens) { // Simulate POIs being submitted @@ -52,10 +52,43 @@ contract SubgraphServiceAllocationCloseStaleTest is SubgraphServiceTest { // Close the stale allocation resetPrank(permissionlessBob); - _closeStaleAllocation(allocationID); + _forceCloseAllocation(allocationID); + } + + function test_SubgraphService_Allocation_ForceClose_OverAllocated( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // thaw some tokens to become over allocated + staking.thaw(users.indexer, address(subgraphService), tokens / 2); + + resetPrank(permissionlessBob); + _forceCloseAllocation(allocationID); + } + + function test_SubgraphService_Allocation_ForceClose_OverAllocated_AfterCollecting( + uint256 tokens + ) public useIndexer useAllocation(tokens) { + // Simulate POIs being submitted + uint8 numberOfPOIs = 5; + uint256 timeBetweenPOIs = 5 days; + + for (uint8 i = 0; i < numberOfPOIs; i++) { + // Skip forward + skip(timeBetweenPOIs); + + bytes memory data = abi.encode(allocationID, bytes32("POI1")); + _collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data); + } + + // thaw some tokens to become over allocated + staking.thaw(users.indexer, address(subgraphService), tokens / 2); + + // Close the over allocated allocation + resetPrank(permissionlessBob); + _forceCloseAllocation(allocationID); } - function test_SubgraphService_Allocation_CloseStale_RevertIf_NotStale( + function test_SubgraphService_Allocation_ForceClose_RevertIf_NotStaleOrOverAllocated( uint256 tokens ) public useIndexer useAllocation(tokens) { // Simulate POIs being submitted @@ -74,16 +107,15 @@ contract SubgraphServiceAllocationCloseStaleTest is SubgraphServiceTest { resetPrank(permissionlessBob); vm.expectRevert( abi.encodeWithSelector( - ISubgraphService.SubgraphServiceAllocationNotStale.selector, - allocationID, - block.timestamp + ISubgraphService.SubgraphServiceCannotForceCloseAllocation.selector, + allocationID ) ); - subgraphService.closeStaleAllocation(allocationID); + subgraphService.forceCloseAllocation(allocationID); } } - function test_SubgraphService_Allocation_CloseStale_RevertIf_Altruistic( + function test_SubgraphService_Allocation_ForceClose_RevertIf_Altruistic( uint256 tokens ) public useIndexer { tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); @@ -103,6 +135,6 @@ contract SubgraphServiceAllocationCloseStaleTest is SubgraphServiceTest { allocationID ) ); - subgraphService.closeStaleAllocation(allocationID); + subgraphService.forceCloseAllocation(allocationID); } } diff --git a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol index 38e9e7865..465f5c8cd 100644 --- a/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol @@ -109,7 +109,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest { } } - function test_SubgraphService_Collect_Indexing_RevertWhen_OverAllocated(uint256 tokens) public useIndexer { + function test_SubgraphService_Collect_Indexing_OverAllocated(uint256 tokens) public useIndexer { tokens = bound(tokens, minimumProvisionTokens * 2, 10_000_000_000 ether); // setup allocation From e33bf12ae2fdbbac69700dc8dc08a04a5ac3f649 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Wed, 2 Oct 2024 10:18:36 +0100 Subject: [PATCH 252/277] fix: revert DisputeManager.sol to previous state --- .../contracts/disputes/DisputeManager.sol | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/contracts/contracts/disputes/DisputeManager.sol b/packages/contracts/contracts/disputes/DisputeManager.sol index fed301de0..6700ec341 100644 --- a/packages/contracts/contracts/disputes/DisputeManager.sol +++ b/packages/contracts/contracts/disputes/DisputeManager.sol @@ -29,7 +29,7 @@ import "./IDisputeManager.sol"; * Indexers present a Proof of Indexing (POI) when they close allocations to prove * they were indexing a subgraph. The Staking contract emits that proof with the format * keccak256(indexer.address, POI). - * Any fisherman can dispute the validity of a POI by submitting a dispute to this contract + * Any challenger can dispute the validity of a POI by submitting a dispute to this contract * along with a deposit. * * Arbitration: @@ -355,8 +355,8 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _deposit Amount of tokens staked as deposit */ function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) external override returns (bytes32) { - // Get funds from fisherman - _pullFishermanDeposit(_deposit); + // Get funds from submitter + _pullSubmitterDeposit(_deposit); // Create a dispute return @@ -372,7 +372,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 fisherman is not required to present a deposit + * 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. @@ -470,14 +470,14 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa /** * @dev Create an indexing dispute for the arbitrator to resolve. * The disputes are created in reference to an allocationID - * This function is called by a fisherman that will need to `_deposit` at + * 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 */ function createIndexingDispute(address _allocationID, uint256 _deposit) external override returns (bytes32) { - // Get funds from fisherman - _pullFishermanDeposit(_deposit); + // Get funds from submitter + _pullSubmitterDeposit(_deposit); // Create a dispute return _createIndexingDisputeWithAllocation(msg.sender, _deposit, _allocationID); @@ -485,7 +485,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa /** * @dev Create indexing dispute internal function. - * @param _fisherman The fisherman creating the dispute + * @param _fisherman The challenger creating the dispute * @param _deposit Amount of tokens staked as deposit * @param _allocationID Allocation disputed */ @@ -606,7 +606,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Draw the conflicting dispute if there is any for the one passed to this function. + * @dev Resolve the conflicting dispute if there is any for the one passed to this function. * @param _dispute Dispute * @return True if resolved */ @@ -621,10 +621,10 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Pull deposit from fisherman account. + * @dev Pull deposit from submitter account. * @param _deposit Amount of tokens to deposit */ - function _pullFishermanDeposit(uint256 _deposit) private { + function _pullSubmitterDeposit(uint256 _deposit) private { // Ensure that fisherman has staked at least the minimum amount require(_deposit >= minimumDeposit, "Dispute deposit is under minimum required"); @@ -633,17 +633,17 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa } /** - * @dev Make the staking contract slash the indexer and reward the fisherman. - * Give the fisherman a reward equal to the fishermanRewardPercentage of slashed amount + * @dev 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 _fisherman Address of the fisherman + * @param _challenger Address of the challenger * @param _disputeType Type of dispute * @return slashAmount Dispute slash amount * @return rewardsAmount Dispute rewards amount */ function _slashIndexer( address _indexer, - address _fisherman, + address _challenger, DisputeType _disputeType ) private returns (uint256 slashAmount, uint256 rewardsAmount) { IStaking staking = staking(); @@ -660,7 +660,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa // Have staking contract slash the indexer and reward the fisherman // Give the fisherman a reward equal to the fishermanRewardPercentage of slashed amount - staking.slash(_indexer, slashAmount, rewardsAmount, _fisherman); + staking.slash(_indexer, slashAmount, rewardsAmount, _challenger); } /** From 2b79a69242553bb07102327b294670cb6db2be42 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Wed, 2 Oct 2024 22:54:39 +1000 Subject: [PATCH 253/277] fix(Horizon): graph directory test (#1054) --- packages/horizon/test/utilities/GraphDirectory.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/test/utilities/GraphDirectory.t.sol b/packages/horizon/test/utilities/GraphDirectory.t.sol index ece4afe65..606933699 100644 --- a/packages/horizon/test/utilities/GraphDirectory.t.sol +++ b/packages/horizon/test/utilities/GraphDirectory.t.sol @@ -27,7 +27,7 @@ contract GraphDirectoryTest is GraphBaseTest { function test_RevertWhen_TheContractIsDeployedWithAnInvalidController(address controller_) external { vm.assume(controller_ != address(controller)); - vm.assume(controller_ != address(0)); + vm.assume(uint160(controller_) > 9); // Skip precompiled contracts vm.expectRevert(); // call to getContractProxy on a random address reverts _deployImplementation(controller_); From dcbcf7e5d001aa54c52575c3c5b6537ced6bec4e Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Wed, 2 Oct 2024 19:11:55 +0100 Subject: [PATCH 254/277] fix: fix broken test --- packages/horizon/test/escrow/collector.t.sol | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index 3e5b71bc0..ed5c05384 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -16,7 +16,12 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { function _approveCollector(uint256 tokens) internal { (uint256 beforeAllowance,) = escrow.authorizedCollectors(users.gateway, users.verifier); vm.expectEmit(address(escrow)); - emit IPaymentsEscrow.AuthorizedCollector(users.gateway, users.verifier); + emit IPaymentsEscrow.AuthorizedCollector( + users.gateway, // payer + users.verifier, // collector + tokens, // addedAllowance + beforeAllowance + tokens // newTotalAllowance after the added allowance + ); escrow.approveCollector(users.verifier, tokens); (uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); assertEq(allowance - beforeAllowance, tokens); From d459928cd7d05c3b1cf6aaa04905ddc76c8d6180 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 <67825802+MoonBoi9001@users.noreply.github.com> Date: Wed, 2 Oct 2024 19:23:43 +0100 Subject: [PATCH 255/277] Update packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomás Migone --- .../contracts/data-service/interfaces/IDataServiceRescuable.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol index 67026f2d4..0c5b2c8f6 100644 --- a/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol +++ b/packages/horizon/contracts/data-service/interfaces/IDataServiceRescuable.sol @@ -16,7 +16,7 @@ interface IDataServiceRescuable is IDataService { * @param token The address of the token being rescued * @param tokens The amount of tokens rescued */ - event TokensRescued(address indexed from, address indexed to, address token, uint256 tokens); + event TokensRescued(address indexed from, address indexed to, address indexed token, uint256 tokens); /** * @notice Emitted when a rescuer is set. From 570b21e52afcefe66f14803402100f76dca3db90 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Thu, 3 Oct 2024 04:30:56 +1000 Subject: [PATCH 256/277] chore(Horizon): add a beneficiary address to undelegate (#1052) --- .../internal/IHorizonStakingMain.sol | 32 +++++++++++ .../contracts/staking/HorizonStaking.sol | 26 +++++++-- .../HorizonStakingShared.t.sol | 22 +++++--- .../test/staking/delegation/undelegate.t.sol | 22 ++++++++ .../test/staking/delegation/withdraw.t.sol | 53 +++++++++++++++++++ 5 files changed, 143 insertions(+), 12 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 6e0cc024f..c0d18366e 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -409,6 +409,11 @@ interface IHorizonStakingMain { */ error HorizonStakingInvalidDelegationPool(address serviceProvider, address verifier); + /** + * @notice Thrown when attempting to undelegate with a beneficiary that is the zero address. + */ + error HorizonStakingInvalidBeneficiaryZeroAddress(); + // -- Errors: thaw requests -- error HorizonStakingNothingThawing(); @@ -706,6 +711,33 @@ interface IHorizonStakingMain { */ function undelegate(address serviceProvider, address verifier, uint256 shares) external returns (bytes32); + /** + * @notice Undelegate tokens from a provision and start thawing them. + * The tokens will be withdrawable by the `beneficiary` after the thawing period. + * + * Note that undelegating tokens from a provision is a two step process: + * - First the tokens are thawed using this function. + * - Then after the thawing period, the tokens are removed from the provision using {withdrawDelegated}. + * + * Requirements: + * - `shares` cannot be zero. + * - `beneficiary` cannot be the zero address. + * + * Emits a {TokensUndelegated} and {ThawRequestCreated} event. + * + * @param serviceProvider The service provider address + * @param verifier The verifier address + * @param shares The amount of shares to undelegate + * @param beneficiary The address where the tokens will be withdrawn after thawing + * @return The ID of the thaw request + */ + function undelegate( + address serviceProvider, + address verifier, + uint256 shares, + address beneficiary + ) external returns (bytes32); + /** * @notice Withdraw undelegated tokens from a provision after thawing. * Tokens can be automatically re-delegated to another provision by setting `newServiceProvider`. diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 22d7c221b..fa566563d 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -302,7 +302,20 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, uint256 shares ) external override notPaused returns (bytes32) { - return _undelegate(serviceProvider, verifier, shares); + return _undelegate(serviceProvider, verifier, shares, msg.sender); + } + + /** + * @notice See {IHorizonStakingMain-undelegate}. + */ + function undelegate( + address serviceProvider, + address verifier, + uint256 shares, + address beneficiary + ) external override notPaused returns (bytes32) { + require(beneficiary != address(0), HorizonStakingInvalidBeneficiaryZeroAddress()); + return _undelegate(serviceProvider, verifier, shares, beneficiary); } /** @@ -345,7 +358,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice See {IHorizonStakingMain-undelegate}. */ function undelegate(address serviceProvider, uint256 shares) external override notPaused { - _undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares); + _undelegate(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, shares, msg.sender); } /** @@ -762,7 +775,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @dev To allow delegation to be slashable even while thawing without breaking accounting * the delegation pool shares are burned and replaced with thawing pool shares. */ - function _undelegate(address _serviceProvider, address _verifier, uint256 _shares) private returns (bytes32) { + function _undelegate( + address _serviceProvider, + address _verifier, + uint256 _shares, + address beneficiary + ) private returns (bytes32) { require(_shares > 0, HorizonStakingInvalidZeroShares()); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); DelegationInternal storage delegation = pool.delegators[msg.sender]; @@ -789,7 +807,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { bytes32 thawRequestId = _createThawRequest( _serviceProvider, _verifier, - msg.sender, + beneficiary, thawingShares, thawingUntil ); diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index e171e455e..fab804e67 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -853,11 +853,17 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { } function _undelegate(address serviceProvider, address verifier, uint256 shares) internal { - __undelegate(serviceProvider, verifier, shares, false); + (, address caller, ) = vm.readCallers(); + __undelegate(serviceProvider, verifier, shares, false, caller); + } + + function _undelegate(address serviceProvider, address verifier, uint256 shares, address beneficiary) internal { + __undelegate(serviceProvider, verifier, shares, false, beneficiary); } function _undelegate(address serviceProvider, uint256 shares) internal { - __undelegate(serviceProvider, subgraphDataServiceLegacyAddress, shares, true); + (, address caller, ) = vm.readCallers(); + __undelegate(serviceProvider, subgraphDataServiceLegacyAddress, shares, true, caller); } struct BeforeValues_Undelegate { @@ -873,7 +879,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { bytes32 thawRequestId; } - function __undelegate(address serviceProvider, address verifier, uint256 shares, bool legacy) private { + function __undelegate(address serviceProvider, address verifier, uint256 shares, bool legacy, address beneficiary) private { (, address delegator, ) = vm.readCallers(); // before @@ -893,7 +899,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { staking.getProvision(serviceProvider, verifier).thawingPeriod + uint64(block.timestamp); calcValues.thawRequestId = keccak256( - abi.encodePacked(serviceProvider, verifier, delegator, beforeValues.thawRequestList.nonce) + abi.encodePacked(serviceProvider, verifier, beneficiary, beforeValues.thawRequestList.nonce) ); // undelegate @@ -901,7 +907,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { emit IHorizonStakingMain.ThawRequestCreated( serviceProvider, verifier, - delegator, + beneficiary, calcValues.thawingShares, calcValues.thawingUntil, calcValues.thawRequestId @@ -911,7 +917,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { if (legacy) { staking.undelegate(serviceProvider, shares); } else { - staking.undelegate(serviceProvider, verifier, shares); + staking.undelegate(serviceProvider, verifier, shares, beneficiary); } // after @@ -923,10 +929,10 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { DelegationInternal memory afterDelegation = _getStorage_Delegation( serviceProvider, verifier, - delegator, + beneficiary, legacy ); - LinkedList.List memory afterThawRequestList = staking.getThawRequestList(serviceProvider, verifier, delegator); + LinkedList.List memory afterThawRequestList = staking.getThawRequestList(serviceProvider, verifier, beneficiary); ThawRequest memory afterThawRequest = staking.getThawRequest(calcValues.thawRequestId); uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable(serviceProvider, verifier); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index cc2492ba8..1ed6469b5 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -40,6 +40,17 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { } } + function testUndelegate_WithBeneficiary( + uint256 amount, + uint256 delegationAmount, + address beneficiary + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + vm.assume(beneficiary != address(0)); + resetPrank(users.delegator); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares, beneficiary); + } + function testUndelegate_RevertWhen_TooManyUndelegations() public useIndexer @@ -133,4 +144,15 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { )); staking.undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); } + + function testUndelegate_RevertIf_BeneficiaryIsZero( + uint256 amount, + uint256 delegationAmount + ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { + resetPrank(users.delegator); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + bytes memory expectedError = abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingInvalidBeneficiaryZeroAddress.selector); + vm.expectRevert(expectedError); + staking.undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares, address(0)); + } } diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index fc9072898..0419c85fc 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -176,4 +176,57 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { )); staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); } + + function testWithdrawDelegation_WithBeneficiary( + uint256 delegationAmount, + address beneficiary + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + { + vm.assume(beneficiary != address(0)); + + // Delegator undelegates to beneficiary + resetPrank(users.delegator); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares, beneficiary); + + // Thawing period ends + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceAddress, beneficiary); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + skip(thawRequest.thawingUntil + 1); + + // Beneficiary withdraws delegated tokens + resetPrank(beneficiary); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 1); + } + + function testWithdrawDelegation_RevertWhen_PreviousOwnerAttemptsToWithdraw( + uint256 delegationAmount, + address beneficiary + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + { + vm.assume(beneficiary != address(0)); + + // Delegator undelegates to beneficiary + resetPrank(users.delegator); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares, beneficiary); + + // Thawing period ends + LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceAddress, users.delegator); + ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); + skip(thawRequest.thawingUntil + 1); + + // Delegator attempts to withdraw delegated tokens, should revert since beneficiary is the thaw request owner + bytes memory expectedError = abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingNothingThawing.selector); + vm.expectRevert(expectedError); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 1); + } } \ No newline at end of file From 4e41890f691eac03fc0d66f0134b2e28abb15119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 3 Oct 2024 11:59:00 -0300 Subject: [PATCH 257/277] feat: remove transfer tools from horizon (#1053) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: remove transfer tools from horizon Signed-off-by: Tomás Migone * fix: deprecate storage variables Signed-off-by: Tomás Migone * fix: remove minimum delegation requirement from delegation flows Signed-off-by: Tomás Migone * fix: minor changes Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone --- .../internal/IHorizonStakingExtension.sol | 23 +-- .../contracts/staking/HorizonStaking.sol | 18 +- .../staking/HorizonStakingExtension.sol | 123 +------------ .../staking/HorizonStakingStorage.sol | 4 +- packages/horizon/test/GraphBase.t.sol | 6 +- packages/horizon/test/escrow/collect.t.sol | 3 +- .../horizon/test/payments/GraphPayments.t.sol | 3 +- .../HorizonStakingShared.t.sol | 107 ----------- .../horizon/test/staking/HorizonStaking.t.sol | 2 +- .../test/staking/allocation/close.t.sol | 2 +- .../test/staking/delegation/addToPool.t.sol | 3 +- .../test/staking/delegation/delegate.t.sol | 22 +-- .../test/staking/delegation/undelegate.t.sol | 25 +-- .../test/staking/delegation/withdraw.t.sol | 14 +- .../test/staking/governance/governance.t.sol | 12 -- .../horizon/test/staking/slash/slash.t.sol | 8 +- .../test/staking/transfer-tools/ttools.t.sol | 166 ------------------ packages/horizon/test/utils/Constants.sol | 1 - .../test/shared/SubgraphServiceShared.t.sol | 3 +- 19 files changed, 30 insertions(+), 515 deletions(-) delete mode 100644 packages/horizon/test/staking/transfer-tools/ttools.t.sol diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol index fcf70cc32..a0b2dc1af 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol @@ -3,13 +3,12 @@ pragma solidity 0.8.27; import { IRewardsIssuer } from "@graphprotocol/contracts/contracts/rewards/IRewardsIssuer.sol"; -import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; /** * @title Interface for {HorizonStakingExtension} contract. - * @notice Provides functions for managing legacy allocations and transfer tools. + * @notice Provides functions for managing legacy allocations. */ -interface IHorizonStakingExtension is IRewardsIssuer, IL2StakingBase { +interface IHorizonStakingExtension is IRewardsIssuer { /** * @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() @@ -39,15 +38,6 @@ interface IHorizonStakingExtension is IRewardsIssuer, IL2StakingBase { Closed } - /** - * @notice Emitted when a delegator delegates through the Graph Token Gateway using the transfer tools. - * @dev TODO(after transfer tools): delete - * @param serviceProvider The address of the service provider. - * @param delegator The address of the delegator. - * @param tokens The amount of tokens delegated. - */ - event StakeDelegated(address indexed serviceProvider, address indexed delegator, uint256 tokens, uint256 shares); - /** * @dev Emitted when `indexer` close an allocation in `epoch` for `allocationID`. * An amount of `tokens` get unallocated from `subgraphDeploymentID`. @@ -87,15 +77,6 @@ interface IHorizonStakingExtension is IRewardsIssuer, IL2StakingBase { uint256 delegationRewards ); - event CounterpartStakingAddressSet(address indexed counterpart); - - /** - * @notice Set the address of the counterpart (L1 or L2) staking contract. - * @dev This function can only be called by the governor. - * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. - */ - function setCounterpartStakingAddress(address counterpart) external; - /** * @notice Close an allocation and free the staked tokens. * To be eligible for rewards a proof of indexing must be presented. diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index fa566563d..325952ddd 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -22,8 +22,7 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * It is designed to be deployed as an upgrade to the L2Staking contract from the legacy contracts package. * @dev It uses a {HorizonStakingExtension} contract to implement the full {IHorizonStaking} interface through delegatecalls. * This is due to the contract size limit on Arbitrum (24kB). The extension contract implements functionality to support - * the legacy staking functions and the transfer tools. Both can be eventually removed without affecting the main - * staking contract. + * the legacy staking functions. It can be eventually removed without affecting the main staking contract. * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ @@ -42,11 +41,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /// @dev Maximum number of simultaneous stake thaw requests (per provision) or undelegations (per delegation) uint256 private constant MAX_THAW_REQUESTS = 100; - /// @dev Minimum amount of delegation to prevent rounding attacks. - /// TODO: remove this after L2 transfer tool for delegation is removed - /// (delegation on L2 has its own slippage protection) - uint256 private constant MIN_DELEGATION = 1e18; - /// @dev Address of the staking extension contract address private immutable STAKING_EXTENSION_ADDRESS; @@ -741,8 +735,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * have been done before calling this function. */ function _delegate(address _serviceProvider, address _verifier, uint256 _tokens, uint256 _minSharesOut) private { - // TODO: remove this after L2 transfer tool for delegation is removed - require(_tokens >= MIN_DELEGATION, HorizonStakingInsufficientTokens(_tokens, MIN_DELEGATION)); require( _provisions[_serviceProvider][_verifier].createdAt != 0, HorizonStakingInvalidProvision(_serviceProvider, _verifier) @@ -795,14 +787,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { pool.sharesThawing = pool.sharesThawing + thawingShares; delegation.shares = delegation.shares - _shares; - // TODO: remove this when L2 transfer tools are removed - if (delegation.shares != 0) { - uint256 remainingTokens = (delegation.shares * (pool.tokens - pool.tokensThawing)) / pool.shares; - require( - remainingTokens >= MIN_DELEGATION, - HorizonStakingInsufficientTokens(remainingTokens, MIN_DELEGATION) - ); - } bytes32 thawRequestId = _createThawRequest( _serviceProvider, diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index d1f08234b..bc878a4f5 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -5,9 +5,6 @@ pragma solidity 0.8.27; import { ICuration } from "@graphprotocol/contracts/contracts/curation/ICuration.sol"; import { IGraphToken } from "@graphprotocol/contracts/contracts/token/IGraphToken.sol"; import { IHorizonStakingExtension } from "../interfaces/internal/IHorizonStakingExtension.sol"; -import { IHorizonStakingTypes } from "../interfaces/internal/IHorizonStakingTypes.sol"; -import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; -import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol"; import { MathUtils } from "../libraries/MathUtils.sol"; @@ -22,18 +19,15 @@ import { HorizonStakingBase } from "./HorizonStakingBase.sol"; * to the Horizon Staking contract. It allows indexers to close allocations and collect pending query fees, but it * does not allow for the creation of new allocations. This should allow indexers to migrate to a subgraph data service * without losing rewards or having service interruptions. - * @dev TODO: Once the transition period and the transfer tools are deemed not necessary this contract - * can be removed. It's expected the transition period to last for a full allocation cycle (28 epochs). + * @dev TODO: Once the transition period passes this contract can be removed. It's expected the transition period to + * last for a full allocation cycle (28 epochs). * @custom:security-contact Please email security+contracts@thegraph.com if you find any * bugs. We may have an active bug bounty program. */ -contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizonStakingExtension { +contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension { using TokenUtils for IGraphToken; using PPMMath for uint256; - /// @dev Minimum amount of tokens that can be delegated - uint256 private constant MINIMUM_DELEGATION = 1e18; - /** * @dev Checks that the sender is the L2GraphTokenGateway as configured on the Controller. */ @@ -53,52 +47,6 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon address subgraphDataServiceAddress ) HorizonStakingBase(controller, subgraphDataServiceAddress) {} - /** - * @notice Receive tokens with a callhook from the bridge. - * @dev The encoded _data can contain information about an service provider's stake - * or a delegator's delegation. - * See L1MessageCodes in IL2Staking for the supported messages. - * @dev "indexer" in this context refers to a service provider (legacy terminology for the bridge) - * @param from Token sender in L1 - * @param tokens Amount of tokens that were transferred - * @param data ABI-encoded callhook data which must include a uint8 code and either a ReceiveIndexerStakeData or ReceiveDelegationData struct. - */ - function onTokenTransfer( - address from, - uint256 tokens, - bytes calldata data - ) external override notPaused onlyL2Gateway { - require(from == _counterpartStakingAddress, "ONLY_L1_STAKING_THROUGH_BRIDGE"); - (uint8 code, bytes memory functionData) = abi.decode(data, (uint8, bytes)); - - if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_INDEXER_STAKE_CODE)) { - IL2StakingTypes.ReceiveIndexerStakeData memory indexerData = abi.decode( - functionData, - (IL2StakingTypes.ReceiveIndexerStakeData) - ); - _receiveIndexerStake(tokens, indexerData); - } else if (code == uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE)) { - IL2StakingTypes.ReceiveDelegationData memory delegationData = abi.decode( - functionData, - (IL2StakingTypes.ReceiveDelegationData) - ); - _receiveDelegation(tokens, delegationData); - } else { - revert("INVALID_CODE"); - } - } - - /** - * @notice Set the address of the counterpart (L1 or L2) staking contract. - * @dev This function can only be called by the governor. - * TODO: Remove after L2 transition period - * @param counterpart Address of the counterpart staking contract in the other chain, without any aliasing. - */ - function setCounterpartStakingAddress(address counterpart) external override onlyGovernor { - _counterpartStakingAddress = counterpart; - emit CounterpartStakingAddressSet(counterpart); - } - /** * @notice Close an allocation and free the staked tokens. * To be eligible for rewards a proof of indexing must be presented. @@ -318,71 +266,6 @@ contract HorizonStakingExtension is HorizonStakingBase, IL2StakingBase, IHorizon return _legacyOperatorAuth[serviceProvider][operator]; } - /** - * @dev 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 _tokens Amount of tokens that were transferred - * @param _indexerData struct containing the indexer's address - */ - function _receiveIndexerStake( - uint256 _tokens, - IL2StakingTypes.ReceiveIndexerStakeData memory _indexerData - ) private { - address indexer = _indexerData.indexer; - // Deposit tokens into the indexer stake - _stake(indexer, _tokens); - } - - /** - * @dev 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. - * @dev Note that L1 staking contract only allows delegation transfer if the indexer has already transferred, - * this means the corresponding delegation pool exists. - * @param _tokens Amount of tokens that were transferred - * @param _delegationData struct containing the delegator's address and the indexer's address - */ - function _receiveDelegation( - uint256 _tokens, - IL2StakingTypes.ReceiveDelegationData memory _delegationData - ) private { - require(_provisions[_delegationData.indexer][SUBGRAPH_DATA_SERVICE_ADDRESS].createdAt != 0, "!provision"); - // Get the delegation pool of the indexer - DelegationPoolInternal storage pool = _legacyDelegationPools[_delegationData.indexer]; - IHorizonStakingTypes.DelegationInternal storage delegation = pool.delegators[_delegationData.delegator]; - - // If pool is in an invalid state, return the tokens to the delegator - if (pool.tokens == 0 && (pool.shares != 0 || pool.sharesThawing != 0)) { - _graphToken().transfer(_delegationData.delegator, _tokens); - emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _tokens); - return; - } - - // Calculate shares to issue (without applying any delegation tax) - uint256 shares = (pool.tokens == 0 || pool.tokens == pool.tokensThawing) - ? _tokens - : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); - - if (shares == 0 || _tokens < MINIMUM_DELEGATION) { - // If no shares would be issued (probably a rounding issue or attack), - // or if the amount is under the minimum delegation (which could be part of a rounding attack), - // return the tokens to the delegator - _graphToken().pushTokens(_delegationData.delegator, _tokens); - emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _tokens); - } else { - // Update the delegation pool - pool.tokens = pool.tokens + _tokens; - pool.shares = pool.shares + shares; - - // Update the individual delegation - delegation.shares = delegation.shares + shares; - - emit StakeDelegated(_delegationData.indexer, _delegationData.delegator, _tokens, shares); - } - } - /** * @dev Collect tax to burn for an amount of tokens. * @param _tokens Total tokens received used to calculate the amount of tax to collect diff --git a/packages/horizon/contracts/staking/HorizonStakingStorage.sol b/packages/horizon/contracts/staking/HorizonStakingStorage.sol index ff515962a..ce2755468 100644 --- a/packages/horizon/contracts/staking/HorizonStakingStorage.sol +++ b/packages/horizon/contracts/staking/HorizonStakingStorage.sol @@ -118,8 +118,8 @@ abstract contract HorizonStakingV1Storage { mapping(address serviceProvider => address rewardsDestination) internal __DEPRECATED_rewardsDestination; /// @dev Address of the counterpart Staking contract on L1/L2 - /// Used for the transfer tools. - address internal _counterpartStakingAddress; + /// Deprecated, transfer tools no longer enabled. + address internal __DEPRECATED_counterpartStakingAddress; /// @dev Address of the StakingExtension implementation /// This is now an immutable variable to save some gas. diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 3c2375b8d..f02733525 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -45,10 +45,8 @@ abstract contract GraphBaseTest is IHorizonStakingTypes, Utils, Constants { address subgraphDataServiceLegacyAddress = makeAddr("subgraphDataServiceLegacyAddress"); address subgraphDataServiceAddress = makeAddr("subgraphDataServiceAddress"); - - // We use these addresses to mock calls from the counterpart staking contract + address graphTokenGatewayAddress = makeAddr("GraphTokenGateway"); - address counterpartStaking = makeAddr("counterpartStaking"); /* Users */ @@ -188,8 +186,6 @@ abstract contract GraphBaseTest is IHorizonStakingTypes, Utils, Constants { proxyAdmin.upgrade(stakingProxy, address(stakingBase)); proxyAdmin.acceptProxy(stakingBase, stakingProxy); staking = IHorizonStaking(address(stakingProxy)); - - staking.setCounterpartStakingAddress(address(counterpartStaking)); } function setupProtocol() private { diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index cbf945515..d9b775b93 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -101,8 +101,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { uint256 tokensDelegatoion = tokens * delegationFeeCut / MAX_PPM; vm.assume(tokensDataService < tokens - tokensProtocol - tokensDelegatoion); - vm.assume(delegationTokens > MIN_DELEGATION); - vm.assume(delegationTokens <= MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); diff --git a/packages/horizon/test/payments/GraphPayments.t.sol b/packages/horizon/test/payments/GraphPayments.t.sol index 8b76678b4..19028bde1 100644 --- a/packages/horizon/test/payments/GraphPayments.t.sol +++ b/packages/horizon/test/payments/GraphPayments.t.sol @@ -119,8 +119,7 @@ contract GraphPaymentsTest is HorizonStakingSharedTest { address escrowAddress = address(escrow); // Delegate tokens - vm.assume(tokensDelegate > MIN_DELEGATION); - vm.assume(tokensDelegate <= MAX_STAKING_TOKENS); + tokensDelegate = bound(tokensDelegate, 1, MAX_STAKING_TOKENS); vm.startPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, tokensDelegate, 0); diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index fab804e67..c0026c5f6 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -8,7 +8,6 @@ import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol import { IHorizonStakingBase } from "../../../contracts/interfaces/internal/IHorizonStakingBase.sol"; import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; import { IHorizonStakingExtension } from "../../../contracts/interfaces/internal/IHorizonStakingExtension.sol"; -import { IL2StakingBase } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingBase.sol"; import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; import { MathUtils } from "../../../contracts/libraries/MathUtils.sol"; @@ -1233,107 +1232,6 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterMaxThawingPeriod, maxThawingPeriod); } - function _setCounterpartStakingAddress(address counterpartStakingAddress) internal { - // setCounterpartStakingAddress - vm.expectEmit(address(staking)); - emit IHorizonStakingExtension.CounterpartStakingAddressSet(counterpartStakingAddress); - staking.setCounterpartStakingAddress(counterpartStakingAddress); - - // after - address afterCounterpartStakingAddress = _getStorage_CounterpartStakingAddress(); - - // assert - assertEq(afterCounterpartStakingAddress, counterpartStakingAddress); - } - - struct BeforeValues_ReceiveDelegation { - DelegationPoolInternalTest pool; - DelegationInternal delegation; - uint256 delegatedTokens; - uint256 stakingBalance; - uint256 delegatorBalance; - } - function _onTokenTransfer_ReceiveDelegation(address from, uint256 tokens, bytes memory data) internal { - address serviceProvider; - address delegator; - { - (, bytes memory fnData) = abi.decode(data, (uint8, bytes)); - (serviceProvider, delegator) = abi.decode(fnData, (address, address)); - } - - // before - BeforeValues_ReceiveDelegation memory beforeValues; - beforeValues.pool = _getStorage_DelegationPoolInternal(serviceProvider, subgraphDataServiceLegacyAddress, true); - beforeValues.delegation = _getStorage_Delegation( - serviceProvider, - subgraphDataServiceLegacyAddress, - delegator, - true - ); - beforeValues.stakingBalance = token.balanceOf(address(staking)); - beforeValues.delegatorBalance = token.balanceOf(delegator); - beforeValues.delegatedTokens = staking.getDelegatedTokensAvailable( - serviceProvider, - subgraphDataServiceLegacyAddress - ); - - // calc - uint256 calcShares = (beforeValues.pool.tokens == 0 || beforeValues.pool.tokens == beforeValues.pool.tokensThawing) - ? tokens - : ((tokens * beforeValues.pool.shares) / (beforeValues.pool.tokens - beforeValues.pool.tokensThawing)); - - bool earlyExit = (calcShares == 0 || tokens < 1 ether) || - (beforeValues.pool.tokens == 0 && (beforeValues.pool.shares != 0 || beforeValues.pool.sharesThawing != 0)); - - // onTokenTransfer - if (earlyExit) { - vm.expectEmit(); - emit Transfer(address(staking), delegator, tokens); - vm.expectEmit(); - emit IL2StakingBase.TransferredDelegationReturnedToDelegator(serviceProvider, delegator, tokens); - } else { - vm.expectEmit(); - emit IHorizonStakingExtension.StakeDelegated(serviceProvider, delegator, tokens, calcShares); - } - staking.onTokenTransfer(from, tokens, data); - - // after - DelegationPoolInternalTest memory afterPool = _getStorage_DelegationPoolInternal(serviceProvider, subgraphDataServiceLegacyAddress, true); - DelegationInternal memory afterDelegation = _getStorage_Delegation( - serviceProvider, - subgraphDataServiceLegacyAddress, - delegator, - true - ); - uint256 afterDelegatedTokens = staking.getDelegatedTokensAvailable( - serviceProvider, - subgraphDataServiceLegacyAddress - ); - uint256 afterDelegatorBalance = token.balanceOf(delegator); - uint256 afterStakingBalance = token.balanceOf(address(staking)); - - // assertions - if (earlyExit) { - assertEq(beforeValues.pool.tokens, afterPool.tokens); - assertEq(beforeValues.pool.shares, afterPool.shares); - assertEq(beforeValues.pool.tokensThawing, afterPool.tokensThawing); - assertEq(beforeValues.pool.sharesThawing, afterPool.sharesThawing); - assertEq(0, afterDelegation.shares - beforeValues.delegation.shares); - assertEq(beforeValues.delegatedTokens, afterDelegatedTokens); - assertEq(beforeValues.delegatorBalance + tokens, afterDelegatorBalance); - assertEq(beforeValues.stakingBalance - tokens, afterStakingBalance); - } else { - assertEq(beforeValues.pool.tokens + tokens, afterPool.tokens); - assertEq(beforeValues.pool.shares + calcShares, afterPool.shares); - assertEq(beforeValues.pool.tokensThawing, afterPool.tokensThawing); - assertEq(beforeValues.pool.sharesThawing, afterPool.sharesThawing); - assertEq(calcShares, afterDelegation.shares - beforeValues.delegation.shares); - assertEq(beforeValues.delegatedTokens + tokens, afterDelegatedTokens); - assertEq(beforeValues.delegatorBalance, afterDelegatorBalance); - assertEq(beforeValues.stakingBalance, afterStakingBalance); - } - } - struct BeforeValues_Slash { Provision provision; DelegationPoolInternalTest pool; @@ -1928,11 +1826,6 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { return delegation; } - function _getStorage_CounterpartStakingAddress() internal view returns (address) { - uint256 slot = 24; - return address(uint160(uint256(vm.load(address(staking), bytes32(slot))))); - } - function _setStorage_allocation( IHorizonStakingExtension.Allocation memory allocation, address allocationId, diff --git a/packages/horizon/test/staking/HorizonStaking.t.sol b/packages/horizon/test/staking/HorizonStaking.t.sol index d846d1754..b1b45d118 100644 --- a/packages/horizon/test/staking/HorizonStaking.t.sol +++ b/packages/horizon/test/staking/HorizonStaking.t.sol @@ -31,7 +31,7 @@ contract HorizonStakingTest is HorizonStakingSharedTest { modifier useDelegation(uint256 delegationAmount) { address msgSender; (, msgSender, ) = vm.readCallers(); - vm.assume(delegationAmount > MIN_DELEGATION); + vm.assume(delegationAmount > 1); vm.assume(delegationAmount <= MAX_STAKING_TOKENS); vm.startPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); diff --git a/packages/horizon/test/staking/allocation/close.t.sol b/packages/horizon/test/staking/allocation/close.t.sol index 121307056..ce3cab273 100644 --- a/packages/horizon/test/staking/allocation/close.t.sol +++ b/packages/horizon/test/staking/allocation/close.t.sol @@ -71,7 +71,7 @@ contract HorizonStakingCloseAllocationTest is HorizonStakingTest { function testCloseAllocation_WithDelegation(uint256 tokens, uint256 delegationTokens, uint32 indexingRewardCut) public useIndexer useAllocation(1 ether) { tokens = bound(tokens, 2, MAX_STAKING_TOKENS); - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 0, MAX_STAKING_TOKENS); vm.assume(indexingRewardCut <= MAX_PPM); uint256 legacyAllocationTokens = tokens / 2; diff --git a/packages/horizon/test/staking/delegation/addToPool.t.sol b/packages/horizon/test/staking/delegation/addToPool.t.sol index b9a583ee8..de2647dfc 100644 --- a/packages/horizon/test/staking/delegation/addToPool.t.sol +++ b/packages/horizon/test/staking/delegation/addToPool.t.sol @@ -9,7 +9,6 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { modifier useValidDelegationAmount(uint256 tokens) { - vm.assume(tokens > MIN_DELEGATION); vm.assume(tokens <= MAX_STAKING_TOKENS); _; } @@ -29,6 +28,8 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { uint256 delegationAmount, uint256 addToPoolAmount ) public useIndexer useProvision(amount, 0, 0) useValidDelegationAmount(delegationAmount) useValidAddToPoolAmount(addToPoolAmount) { + delegationAmount = bound(delegationAmount, 1, MAX_STAKING_TOKENS); + // Initialize delegation pool resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index d5e101bca..5deb9b495 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -59,25 +59,9 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { staking.delegate(users.indexer, subgraphDataServiceAddress, 0, 0); } - function testDelegate_RevertWhen_BelowMinimum( - uint256 amount, - uint256 delegationAmount - ) public useIndexer useProvision(amount, 0, 0) { - vm.startPrank(users.delegator); - delegationAmount = bound(delegationAmount, 1, MIN_DELEGATION - 1); - token.approve(address(staking), delegationAmount); - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokens(uint256,uint256)", - delegationAmount, - MIN_DELEGATION - ); - vm.expectRevert(expectedError); - staking.delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); - } - function testDelegate_LegacySubgraphService(uint256 amount, uint256 delegationAmount) public useIndexer { amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); - delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationAmount = bound(delegationAmount, 1, MAX_STAKING_TOKENS); _createProvision(users.indexer, subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); @@ -88,7 +72,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { uint256 tokens, uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); @@ -109,7 +93,7 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { uint256 tokens, uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index 1ed6469b5..c5d61b6e5 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -27,14 +27,13 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 undelegateSteps ) public useIndexer useProvision(amount, 0, 0) { undelegateSteps = bound(undelegateSteps, 1, 10); - delegationAmount = bound(delegationAmount, MIN_DELEGATION + 10 wei, MAX_STAKING_TOKENS); + delegationAmount = bound(delegationAmount, 10 wei, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); - // there is a min delegation amount of 1 ether after undelegating - uint256 undelegateAmount = (delegation.shares - 1 ether) / undelegateSteps; + uint256 undelegateAmount = delegation.shares / undelegateSteps; for (uint i = 0; i < undelegateSteps; i++) { _undelegate(users.indexer, subgraphDataServiceAddress, undelegateAmount); } @@ -96,25 +95,9 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { staking.undelegate(users.indexer, subgraphDataServiceAddress, overDelegationShares); } - function testUndelegate_RevertWhen_UndelegateLeavesInsufficientTokens( - uint256 delegationAmount, - uint256 withdrawShares - ) public useIndexer useProvision(10_000_000 ether, 0, 0) useDelegation(delegationAmount) { - resetPrank(users.delegator); - uint256 minShares = delegationAmount - MIN_DELEGATION + 1; - withdrawShares = bound(withdrawShares, minShares, delegationAmount - 1); - bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInsufficientTokens(uint256,uint256)", - delegationAmount - withdrawShares, - MIN_DELEGATION - ); - vm.expectRevert(expectedError); - staking.undelegate(users.indexer, subgraphDataServiceAddress, withdrawShares); - } - function testUndelegate_LegacySubgraphService(uint256 amount, uint256 delegationAmount) public useIndexer { amount = bound(amount, 1, MAX_STAKING_TOKENS); - delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationAmount = bound(delegationAmount, 1, MAX_STAKING_TOKENS); _createProvision(users.indexer, subgraphDataServiceLegacyAddress, amount, 0, 0); resetPrank(users.delegator); @@ -128,7 +111,7 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 tokens, uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 0419c85fc..866f49942 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -19,15 +19,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { vm.startPrank(users.delegator); DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); shares = bound(shares, 1, delegation.shares); - - if (shares != delegation.shares) { - DelegationPoolInternalTest memory pool = _getStorage_DelegationPoolInternal(users.indexer, subgraphDataServiceAddress, false); - uint256 tokens = (shares * (pool.tokens - pool.tokensThawing)) / pool.shares; - uint256 newTokensThawing = pool.tokensThawing + tokens; - uint256 remainingTokens = (delegation.shares * (pool.tokens - newTokensThawing)) / pool.shares; - vm.assume(remainingTokens >= MIN_DELEGATION); - } - + _undelegate(users.indexer, subgraphDataServiceAddress, shares); _; } @@ -137,7 +129,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { } function testWithdrawDelegation_LegacySubgraphService(uint256 delegationAmount) public useIndexer { - delegationAmount = bound(delegationAmount, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationAmount = bound(delegationAmount, 1, MAX_STAKING_TOKENS); _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 10_000_000 ether, 0, MAX_THAWING_PERIOD); resetPrank(users.delegator); @@ -157,7 +149,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { uint256 tokens, uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, MAX_THAWING_PERIOD) useDelegationSlashing() { - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); diff --git a/packages/horizon/test/staking/governance/governance.t.sol b/packages/horizon/test/staking/governance/governance.t.sol index 401828a3e..434364a80 100644 --- a/packages/horizon/test/staking/governance/governance.t.sol +++ b/packages/horizon/test/staking/governance/governance.t.sol @@ -62,16 +62,4 @@ contract HorizonStakingGovernanceTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.setMaxThawingPeriod(MAX_THAWING_PERIOD); } - - function testGovernance_SetCounterpartStakingAddress(address counterpartStakingAddress) public useGovernor { - _setCounterpartStakingAddress(counterpartStakingAddress); - } - - function testGovernance_RevertWhen_SetCounterpartStakingAddress_NotGovernor( - address counterpartStakingAddress - ) public useIndexer { - bytes memory expectedError = abi.encodeWithSignature("ManagedOnlyGovernor()"); - vm.expectRevert(expectedError); - staking.setCounterpartStakingAddress(counterpartStakingAddress); - } } \ No newline at end of file diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index bf1f2fb1e..aea8db986 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -54,7 +54,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 delegationTokens ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) { vm.assume(slashTokens > tokens); - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); uint256 maxVerifierTokens = (tokens * MAX_MAX_VERIFIER_CUT) / MAX_PPM; vm.assume(verifierCutAmount <= maxVerifierTokens); @@ -72,8 +72,8 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 verifierCutAmount, uint256 delegationTokens ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing() { - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); - slashTokens = bound(slashTokens, tokens + 1, tokens + delegationTokens); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + slashTokens = bound(slashTokens, tokens + 1, tokens + 1 + delegationTokens); verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); uint256 maxVerifierTokens = (tokens * MAX_MAX_VERIFIER_CUT) / MAX_PPM; vm.assume(verifierCutAmount <= maxVerifierTokens); @@ -90,7 +90,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 slashTokens, uint256 delegationTokens ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) { - delegationTokens = bound(delegationTokens, MIN_DELEGATION, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 0, MAX_STAKING_TOKENS); vm.assume(slashTokens > tokens + delegationTokens); vm.startPrank(subgraphDataServiceAddress); diff --git a/packages/horizon/test/staking/transfer-tools/ttools.t.sol b/packages/horizon/test/staking/transfer-tools/ttools.t.sol deleted file mode 100644 index 11bb6e62d..000000000 --- a/packages/horizon/test/staking/transfer-tools/ttools.t.sol +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.27; - -import "forge-std/Test.sol"; - -import { HorizonStakingTest } from "../HorizonStaking.t.sol"; -import { IL2StakingTypes } from "@graphprotocol/contracts/contracts/l2/staking/IL2StakingTypes.sol"; - -contract HorizonStakingTransferToolsTest is HorizonStakingTest { - /* - * TESTS - */ - - function testOnTransfer_RevertWhen_InvalidCaller() public { - bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 - vm.expectRevert(bytes("ONLY_GATEWAY")); - staking.onTokenTransfer(counterpartStaking, 0, data); - } - - function testOnTransfer_RevertWhen_InvalidCounterpart() public { - resetPrank(graphTokenGatewayAddress); - - bytes memory data = abi.encode(uint8(0), new bytes(0)); // Valid codes are 0 and 1 - vm.expectRevert(bytes("ONLY_L1_STAKING_THROUGH_BRIDGE")); - staking.onTokenTransfer(address(staking), 0, data); - } - - function testOnTransfer_RevertWhen_InvalidData() public { - resetPrank(graphTokenGatewayAddress); - - vm.expectRevert(); - staking.onTokenTransfer(counterpartStaking, 0, new bytes(0)); - } - - function testOnTransfer_RevertWhen_InvalidCode() public { - resetPrank(graphTokenGatewayAddress); - - bytes memory data = abi.encode(uint8(2), new bytes(0)); // Valid codes are 0 and 1 - vm.expectRevert(bytes("INVALID_CODE")); - staking.onTokenTransfer(counterpartStaking, 0, data); - } - - function testOnTransfer_RevertWhen_ProvisionNotFound(uint256 amount) public { - amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); - - resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode( - uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), - abi.encode(users.indexer, users.delegator) - ); - vm.expectRevert(bytes("!provision")); - staking.onTokenTransfer(counterpartStaking, amount, data); - } - - function testOnTransfer_ReceiveDelegation_RevertWhen_InvalidData() public { - resetPrank(graphTokenGatewayAddress); - - bytes memory data = abi.encode(uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), new bytes(0)); - vm.expectRevert(); - staking.onTokenTransfer(counterpartStaking, 0, data); - } - - function testOnTransfer_ReceiveDelegation(uint256 amount) public { - amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); - - // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 - resetPrank(users.indexer); - _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 100 ether, 0, 0); - - resetPrank(users.delegator); - _delegate(users.indexer, 1 ether); - - // send amount to staking contract - this should be done by the bridge - resetPrank(users.delegator); - token.transfer(address(staking), amount); - - resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode( - uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), - abi.encode(users.indexer, users.delegator) - ); - _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); - } - - function testOnTransfer_ReceiveDelegation_WhenThawing(uint256 amount) public { - amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); - uint256 originalDelegationAmount = 10 ether; - - // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 - resetPrank(users.indexer); - _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); - - resetPrank(users.delegator); - _delegate(users.indexer, originalDelegationAmount); - - // send amount to staking contract - this should be done by the bridge - resetPrank(users.delegator); - token.transfer(address(staking), amount); - - // thaw some delegation before receiving new delegation from L1 - resetPrank(users.delegator); - _undelegate(users.indexer, originalDelegationAmount / 10); - - resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode( - uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), - abi.encode(users.indexer, users.delegator) - ); - _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); - } - - function testOnTransfer_ReceiveDelegation_WhenInvalidPool(uint256 amount) public useDelegationSlashing() { - amount = bound(amount, 1 ether, MAX_STAKING_TOKENS); - uint256 originalDelegationAmount = 10 ether; - uint256 provisionSize = 100 ether; - - // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 - resetPrank(users.indexer); - _createProvision(users.indexer, subgraphDataServiceLegacyAddress, provisionSize, 0, 1 days); - - // initialize the delegation pool - resetPrank(users.delegator); - _delegate(users.indexer, originalDelegationAmount); - - // slash the entire provision - resetPrank(subgraphDataServiceLegacyAddress); - _slash(users.indexer, subgraphDataServiceLegacyAddress, provisionSize + originalDelegationAmount, 0); - - // send amount to staking contract - this should be done by the bridge - resetPrank(users.delegator); - token.transfer(address(staking), amount); - - resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode( - uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), - abi.encode(users.indexer, users.delegator) - ); - _onTokenTransfer_ReceiveDelegation(counterpartStaking, amount, data); - } - function testOnTransfer_ReceiveDelegation_WhenAllThawing(uint256 amountReceived, uint256 amountDelegated) public { - amountReceived = bound(amountReceived, 1 ether, MAX_STAKING_TOKENS); - amountDelegated = bound(amountDelegated, 1 ether, MAX_STAKING_TOKENS); - - // create provision and legacy delegation pool - this is done by the bridge when indexers move to L2 - resetPrank(users.indexer); - _createProvision(users.indexer, subgraphDataServiceLegacyAddress, 100 ether, 0, 1 days); - - resetPrank(users.delegator); - _delegate(users.indexer, amountDelegated); - - // send amount to staking contract - this should be done by the bridge - resetPrank(users.delegator); - token.transfer(address(staking), amountReceived); - - // thaw all delegation before receiving new delegation from L1 - resetPrank(users.delegator); - _undelegate(users.indexer, amountDelegated); - - resetPrank(graphTokenGatewayAddress); - bytes memory data = abi.encode( - uint8(IL2StakingTypes.L1MessageCodes.RECEIVE_DELEGATION_CODE), - abi.encode(users.indexer, users.delegator) - ); - _onTokenTransfer_ReceiveDelegation(counterpartStaking, amountReceived, data); - } -} diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index f08fa4ec1..270bb1e43 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -14,7 +14,6 @@ abstract contract Constants { uint256 internal constant MAX_THAW_REQUESTS = 100; uint32 internal constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% in parts per million uint64 internal constant MAX_THAWING_PERIOD = 28 days; - uint256 internal constant MIN_DELEGATION = 1 ether; uint32 internal constant THAWING_PERIOD_IN_BLOCKS = 300; // Epoch manager uint256 internal constant EPOCH_LENGTH = 1; diff --git a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol index 089fdd9a9..d0f28fcec 100644 --- a/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol +++ b/packages/subgraph-service/test/shared/SubgraphServiceShared.t.sol @@ -41,8 +41,7 @@ abstract contract SubgraphServiceSharedTest is HorizonStakingSharedTest { } modifier useDelegation(uint256 tokens) { - // 1e18 is the minimum delegation amount until L2 transfers are removed - vm.assume(tokens > 1e18); + vm.assume(tokens > 1); vm.assume(tokens < 10_000_000_000 ether); (, address msgSender,) = vm.readCallers(); resetPrank(users.delegator); From 2284a3daf7fa19c2a790717290781b0e1ae32d15 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Fri, 4 Oct 2024 02:34:30 +1000 Subject: [PATCH 258/277] fix(Horizon): add input validation for set provision parameters (#1055) * fix(Horizon): add input validation for set provision parameters * fix: subgraph service tests * fix: use new parameter names * fix: subgraph-service tests --- .../internal/IHorizonStakingMain.sol | 5 +- .../contracts/staking/HorizonStaking.sol | 14 +++--- .../HorizonStakingShared.t.sol | 2 +- .../test/staking/provision/locked.t.sol | 6 +-- .../test/staking/provision/parameters.t.sol | 48 ++++++++++++++++++- .../test/staking/provision/provision.t.sol | 9 ++-- .../serviceProvider/serviceProvider.t.sol | 8 ++-- .../horizon/test/staking/slash/slash.t.sol | 15 +++--- packages/horizon/test/utils/Constants.sol | 3 +- .../subgraphService/provision/accept.t.sol | 4 +- .../subgraph-service/test/utils/Constants.sol | 2 +- 11 files changed, 76 insertions(+), 40 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index c0d18366e..210146bf4 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -341,9 +341,8 @@ interface IHorizonStakingMain { /** * @notice Thrown when attempting to create a provision with an invalid maximum verifier cut. * @param maxVerifierCut The maximum verifier cut - * @param maxMaxVerifierCut The maximum `maxVerifierCut` allowed */ - error HorizonStakingInvalidMaxVerifierCut(uint32 maxVerifierCut, uint32 maxMaxVerifierCut); + error HorizonStakingInvalidMaxVerifierCut(uint32 maxVerifierCut); /** * @notice Thrown when attempting to create a provision with an invalid thawing period. @@ -528,7 +527,7 @@ interface IHorizonStakingMain { * @dev Requirements: * - `tokens` cannot be zero. * - The `serviceProvider` must have enough idle stake to cover the tokens to provision. - * - `maxVerifierCut` must be less than or equal to `MAX_MAX_VERIFIER_CUT`. + * - `maxVerifierCut` must be a valid PPM. * - `thawingPeriod` must be less than or equal to `_maxThawingPeriod`. * * Emits a {ProvisionCreated} event. diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 325952ddd..a00cda8af 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -31,10 +31,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { using PPMMath for uint256; using LinkedList for LinkedList.List; - /// @dev Maximum value that can be set as the maxVerifierCut in a provision. - /// It is equivalent to 100% in parts-per-million - uint32 private constant MAX_MAX_VERIFIER_CUT = uint32(PPMMath.MAX_PPM); - /// @dev Fixed point precision uint256 private constant FIXED_POINT_PRECISION = 1e18; @@ -224,6 +220,11 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint32 newMaxVerifierCut, uint64 newThawingPeriod ) external override notPaused onlyAuthorized(serviceProvider, verifier) { + require(PPMMath.isValidPPM(newMaxVerifierCut), HorizonStakingInvalidMaxVerifierCut(newMaxVerifierCut)); + require( + newThawingPeriod <= _maxThawingPeriod, + HorizonStakingInvalidThawingPeriod(newThawingPeriod, _maxThawingPeriod) + ); Provision storage prov = _provisions[serviceProvider][verifier]; require(prov.createdAt != 0, HorizonStakingInvalidProvision(serviceProvider, verifier)); @@ -626,10 +627,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint64 _thawingPeriod ) private { require(_tokens > 0, HorizonStakingInvalidZeroTokens()); - require( - _maxVerifierCut <= MAX_MAX_VERIFIER_CUT, - HorizonStakingInvalidMaxVerifierCut(_maxVerifierCut, MAX_MAX_VERIFIER_CUT) - ); + require(PPMMath.isValidPPM(_maxVerifierCut), HorizonStakingInvalidMaxVerifierCut(_maxVerifierCut)); require( _thawingPeriod <= _maxThawingPeriod, HorizonStakingInvalidThawingPeriod(_thawingPeriod, _maxThawingPeriod) diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index c0026c5f6..f9796cf94 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -81,7 +81,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { // use assume instead of bound to avoid the bounding falling out of scope vm.assume(tokens > 0); vm.assume(tokens <= MAX_STAKING_TOKENS); - vm.assume(maxVerifierCut <= MAX_MAX_VERIFIER_CUT); + vm.assume(maxVerifierCut <= MAX_PPM); vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); _createProvision(users.indexer, dataService, tokens, maxVerifierCut, thawingPeriod); diff --git a/packages/horizon/test/staking/provision/locked.t.sol b/packages/horizon/test/staking/provision/locked.t.sol index a8adfc774..a4d8eda92 100644 --- a/packages/horizon/test/staking/provision/locked.t.sol +++ b/packages/horizon/test/staking/provision/locked.t.sol @@ -24,7 +24,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { users.indexer, subgraphDataServiceAddress, amount, - MAX_MAX_VERIFIER_CUT, + MAX_PPM, MAX_THAWING_PERIOD ); @@ -52,7 +52,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { users.indexer, subgraphDataServiceAddress, amount, - MAX_MAX_VERIFIER_CUT, + MAX_PPM, MAX_THAWING_PERIOD ); } @@ -75,7 +75,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { users.indexer, subgraphDataServiceAddress, amount, - MAX_MAX_VERIFIER_CUT, + MAX_PPM, MAX_THAWING_PERIOD ); } diff --git a/packages/horizon/test/staking/provision/parameters.t.sol b/packages/horizon/test/staking/provision/parameters.t.sol index 8171f95b4..6eccca06e 100644 --- a/packages/horizon/test/staking/provision/parameters.t.sol +++ b/packages/horizon/test/staking/provision/parameters.t.sol @@ -7,6 +7,17 @@ import { HorizonStakingTest } from "../HorizonStaking.t.sol"; import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; contract HorizonStakingProvisionParametersTest is HorizonStakingTest { + + /* + * MODIFIERS + */ + + modifier useValidParameters(uint32 maxVerifierCut, uint64 thawingPeriod) { + vm.assume(maxVerifierCut <= MAX_PPM); + vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); + _; + } + /* * TESTS */ @@ -15,14 +26,14 @@ contract HorizonStakingProvisionParametersTest is HorizonStakingTest { uint256 amount, uint32 maxVerifierCut, uint64 thawingPeriod - ) public useIndexer useProvision(amount, 0, 0) { + ) public useIndexer useProvision(amount, 0, 0) useValidParameters(maxVerifierCut, thawingPeriod) { _setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); } function test_ProvisionParametersSet_RevertWhen_ProvisionNotExists( uint32 maxVerifierCut, uint64 thawingPeriod - ) public useIndexer { + ) public useIndexer useValidParameters(maxVerifierCut, thawingPeriod) { vm.expectRevert( abi.encodeWithSignature( "HorizonStakingInvalidProvision(address,address)", @@ -71,4 +82,37 @@ contract HorizonStakingProvisionParametersTest is HorizonStakingTest { _acceptProvisionParameters(users.indexer); vm.stopPrank(); } + + function test_ProvisionParameters_RevertIf_InvalidMaxVerifierCut( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + maxVerifierCut = uint32(bound(maxVerifierCut, MAX_PPM + 1, type(uint32).max)); + vm.assume(thawingPeriod <= MAX_THAWING_PERIOD); + vm.expectRevert( + abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidMaxVerifierCut.selector, + maxVerifierCut + ) + ); + staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + } + + function test_ProvisionParameters_RevertIf_InvalidThawingPeriod( + uint256 amount, + uint32 maxVerifierCut, + uint64 thawingPeriod + ) public useIndexer useProvision(amount, maxVerifierCut, thawingPeriod) { + vm.assume(maxVerifierCut <= MAX_PPM); + thawingPeriod = uint64(bound(thawingPeriod, MAX_THAWING_PERIOD + 1, type(uint64).max)); + vm.expectRevert( + abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidThawingPeriod.selector, + thawingPeriod, + MAX_THAWING_PERIOD + ) + ); + staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); + } } diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index 50dc12057..cabe2f25e 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -12,7 +12,7 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { function testProvision_Create(uint256 tokens, uint32 maxVerifierCut, uint64 thawingPeriod) public useIndexer { tokens = bound(tokens, 1, MAX_STAKING_TOKENS); - maxVerifierCut = uint32(bound(maxVerifierCut, 0, MAX_MAX_VERIFIER_CUT)); + maxVerifierCut = uint32(bound(maxVerifierCut, 0, MAX_PPM)); thawingPeriod = uint32(bound(thawingPeriod, 0, MAX_THAWING_PERIOD)); _createProvision(users.indexer, subgraphDataServiceAddress, tokens, maxVerifierCut, thawingPeriod); @@ -28,11 +28,10 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { uint256 amount, uint32 maxVerifierCut ) public useIndexer useStake(amount) { - vm.assume(maxVerifierCut > MAX_MAX_VERIFIER_CUT); + vm.assume(maxVerifierCut > MAX_PPM); bytes memory expectedError = abi.encodeWithSignature( - "HorizonStakingInvalidMaxVerifierCut(uint32,uint32)", - maxVerifierCut, - MAX_MAX_VERIFIER_CUT + "HorizonStakingInvalidMaxVerifierCut(uint32)", + maxVerifierCut ); vm.expectRevert(expectedError); staking.provision(users.indexer, subgraphDataServiceAddress, amount, maxVerifierCut, 0); diff --git a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol index 63578791a..7db480869 100644 --- a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol +++ b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol @@ -84,7 +84,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { uint256 amount, uint256 delegationAmount, uint32 delegationRatio - ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { + ) public useIndexer useProvision(amount, MAX_PPM, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { uint256 tokensAvailable = staking.getTokensAvailable(users.indexer, subgraphDataServiceAddress, delegationRatio); uint256 tokensDelegatedMax = amount * (uint256(delegationRatio)); @@ -95,7 +95,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { function testServiceProvider_GetProviderTokensAvailable( uint256 amount, uint256 delegationAmount - ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { + ) public useIndexer useProvision(amount, MAX_PPM, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { uint256 providerTokensAvailable = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); // Should not include delegated tokens assertEq(providerTokensAvailable, amount); @@ -103,7 +103,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { function testServiceProvider_HasStake( uint256 amount - ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) { + ) public useIndexer useProvision(amount, MAX_PPM, MAX_THAWING_PERIOD) { assertTrue(staking.hasStake(users.indexer)); _thaw(users.indexer, subgraphDataServiceAddress, amount); @@ -116,7 +116,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { function testServiceProvider_GetIndexerStakedTokens( uint256 amount - ) public useIndexer useProvision(amount, MAX_MAX_VERIFIER_CUT, MAX_THAWING_PERIOD) { + ) public useIndexer useProvision(amount, MAX_PPM, MAX_THAWING_PERIOD) { assertEq(staking.getIndexerStakedTokens(users.indexer), amount); _thaw(users.indexer, subgraphDataServiceAddress, amount); diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index aea8db986..66a645b7a 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -52,12 +52,11 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 slashTokens, uint256 verifierCutAmount, uint256 delegationTokens - ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) { + ) public useIndexer useProvision(tokens, MAX_PPM, 0) { vm.assume(slashTokens > tokens); delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); - verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); - uint256 maxVerifierTokens = (tokens * MAX_MAX_VERIFIER_CUT) / MAX_PPM; - vm.assume(verifierCutAmount <= maxVerifierTokens); + verifierCutAmount = bound(verifierCutAmount, 0, MAX_PPM); + vm.assume(verifierCutAmount <= tokens); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); @@ -71,12 +70,10 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 slashTokens, uint256 verifierCutAmount, uint256 delegationTokens - ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) useDelegationSlashing() { + ) public useIndexer useProvision(tokens, MAX_PPM, 0) useDelegationSlashing() { delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); slashTokens = bound(slashTokens, tokens + 1, tokens + 1 + delegationTokens); - verifierCutAmount = bound(verifierCutAmount, 0, MAX_MAX_VERIFIER_CUT); - uint256 maxVerifierTokens = (tokens * MAX_MAX_VERIFIER_CUT) / MAX_PPM; - vm.assume(verifierCutAmount <= maxVerifierTokens); + verifierCutAmount = bound(verifierCutAmount, 0, tokens); resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); @@ -89,7 +86,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { uint256 tokens, uint256 slashTokens, uint256 delegationTokens - ) public useIndexer useProvision(tokens, MAX_MAX_VERIFIER_CUT, 0) { + ) public useIndexer useProvision(tokens, MAX_PPM, 0) { delegationTokens = bound(delegationTokens, 0, MAX_STAKING_TOKENS); vm.assume(slashTokens > tokens + delegationTokens); diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index 270bb1e43..5b1449ea7 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.27; abstract contract Constants { - uint256 internal constant MAX_PPM = 1000000; // 100% in parts per million + uint32 internal constant MAX_PPM = 1000000; // 100% in parts per million uint256 internal constant delegationFeeCut = 100000; // 10% in parts per million uint256 internal constant MAX_STAKING_TOKENS = 10_000_000_000 ether; // GraphEscrow parameters @@ -12,7 +12,6 @@ abstract contract Constants { uint256 internal constant protocolPaymentCut = 10000; // Staking constants uint256 internal constant MAX_THAW_REQUESTS = 100; - uint32 internal constant MAX_MAX_VERIFIER_CUT = 1000000; // 100% in parts per million uint64 internal constant MAX_THAWING_PERIOD = 28 days; uint32 internal constant THAWING_PERIOD_IN_BLOCKS = 300; // Epoch manager diff --git a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol index 44ce19b5f..812a27639 100644 --- a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol +++ b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol @@ -22,7 +22,7 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); vm.assume(newVerifierCut >= fishermanRewardPercentage); vm.assume(newVerifierCut <= MAX_PPM); - vm.assume(newDisputePeriod >= disputePeriod); + newDisputePeriod = uint64(bound(newDisputePeriod, disputePeriod, MAX_WAIT_PERIOD)); // Setup indexer _createProvision(users.indexer, tokens, fishermanRewardPercentage, disputePeriod); @@ -58,7 +58,7 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { uint32 newVerifierCut ) public useIndexer { tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS); - vm.assume(newVerifierCut > MAX_PPM); + vm.assume(newVerifierCut < maxSlashingPercentage); // Setup indexer _createProvision(users.indexer, tokens, fishermanRewardPercentage, disputePeriod); diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index eabf5e7b2..f1aac3d16 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -6,7 +6,7 @@ abstract contract Constants { uint256 internal constant MAX_PPM = 1_000_000; uint256 internal constant EPOCH_LENGTH = 1; // Dispute Manager - uint64 internal constant disputePeriod = 300; // 5 minutes + uint64 internal constant disputePeriod = 7 days; uint256 internal constant disputeDeposit = 100 ether; // 100 GRT uint32 internal constant fishermanRewardPercentage = 500000; // 50% uint32 internal constant maxSlashingPercentage = 500000; // 50% From f88f33519f2e267ab623a98bf7dbd07177b37692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 4 Oct 2024 13:29:32 -0300 Subject: [PATCH 259/277] feat: add rav collected event (#1056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../contracts/interfaces/ITAPCollector.sol | 20 +++++++++++++++++++ .../payments/collectors/TAPCollector.sol | 9 +++++++++ 2 files changed, 29 insertions(+) diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 6cfc16485..72a8dc0bc 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -34,6 +34,26 @@ interface ITAPCollector is IPaymentsCollector { bytes signature; } + /** + * @notice Emitted when a RAV is collected + * @param payer The address of the payer + * @param dataService The address of the data service + * @param serviceProvider The address of the service provider + * @param timestampNs The timestamp of the RAV + * @param valueAggregate The total amount owed to the service provider + * @param metadata Arbitrary metadata + * @param signature The signature of the RAV + */ + event RAVCollected( + address indexed payer, + address indexed dataService, + address indexed serviceProvider, + uint64 timestampNs, + uint128 valueAggregate, + bytes metadata, + bytes signature + ); + /** * Thrown when the caller is not the data service the RAV was issued to * @param caller The address of the caller diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index f9b228ead..91293af09 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -85,6 +85,15 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { } emit PaymentCollected(paymentType, payer, receiver, tokensToCollect, dataService, tokensDataService); + emit RAVCollected( + payer, + dataService, + receiver, + signedRAV.rav.timestampNs, + signedRAV.rav.valueAggregate, + signedRAV.rav.metadata, + signedRAV.signature + ); return tokensToCollect; } From e40c8fe49c25c3a119223f7aafeb8c677e95db5d Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Tue, 8 Oct 2024 01:03:45 +1100 Subject: [PATCH 260/277] fix(Horizon): withdraw delegation with beneficiary test fix (#1057) * fix(Horizon): withdraw delegation with beneficiary test fix * fix: skip addresses that will overflow --- packages/horizon/test/staking/delegation/withdraw.t.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 866f49942..b7644c62a 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -179,6 +179,8 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useDelegation(delegationAmount) { vm.assume(beneficiary != address(0)); + // Skip beneficiary if balance will overflow + vm.assume(token.balanceOf(beneficiary) < type(uint256).max - delegationAmount); // Delegator undelegates to beneficiary resetPrank(users.delegator); From 8b3a86b7d8a277b9761a94f43e3ae84e5b3e9568 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Thu, 3 Oct 2024 13:29:29 +0100 Subject: [PATCH 261/277] fix: apply consistent mapping order HorizonStakingNotAuthorized (OZ_N-05) --- .../contracts/interfaces/internal/IHorizonStakingMain.sol | 2 +- packages/horizon/contracts/staking/HorizonStaking.sol | 2 +- packages/horizon/test/staking/provision/deprovision.t.sol | 4 ++-- packages/horizon/test/staking/provision/locked.t.sol | 4 ++-- packages/horizon/test/staking/provision/parameters.t.sol | 4 ++-- packages/horizon/test/staking/provision/provision.t.sol | 4 ++-- packages/horizon/test/staking/provision/reprovision.t.sol | 4 ++-- packages/horizon/test/staking/provision/thaw.t.sol | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 210146bf4..002f9e9b3 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -336,7 +336,7 @@ interface IHorizonStakingMain { * @param serviceProvider The service provider address * @param verifier The verifier address */ - error HorizonStakingNotAuthorized(address caller, address serviceProvider, address verifier); + error HorizonStakingNotAuthorized(address serviceProvider, address verifier, address caller); /** * @notice Thrown when attempting to create a provision with an invalid maximum verifier cut. diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index a00cda8af..b6009043a 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -48,7 +48,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { modifier onlyAuthorized(address serviceProvider, address verifier) { require( _isAuthorized(msg.sender, serviceProvider, verifier), - HorizonStakingNotAuthorized(msg.sender, serviceProvider, verifier) + HorizonStakingNotAuthorized(serviceProvider, verifier, msg.sender) ); _; } diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index 6d03c3f6e..376b05e14 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -75,9 +75,9 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingNotAuthorized(address,address,address)", - users.operator, users.indexer, - subgraphDataServiceAddress + subgraphDataServiceAddress, + users.operator ); vm.expectRevert(expectedError); staking.deprovision(users.indexer, subgraphDataServiceAddress, 0); diff --git a/packages/horizon/test/staking/provision/locked.t.sol b/packages/horizon/test/staking/provision/locked.t.sol index a4d8eda92..66745839b 100644 --- a/packages/horizon/test/staking/provision/locked.t.sol +++ b/packages/horizon/test/staking/provision/locked.t.sol @@ -66,9 +66,9 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingNotAuthorized(address,address,address)", - users.operator, users.indexer, - subgraphDataServiceAddress + subgraphDataServiceAddress, + users.operator ); vm.expectRevert(expectedError); staking.provisionLocked( diff --git a/packages/horizon/test/staking/provision/parameters.t.sol b/packages/horizon/test/staking/provision/parameters.t.sol index 6eccca06e..377684630 100644 --- a/packages/horizon/test/staking/provision/parameters.t.sol +++ b/packages/horizon/test/staking/provision/parameters.t.sol @@ -53,9 +53,9 @@ contract HorizonStakingProvisionParametersTest is HorizonStakingTest { vm.expectRevert( abi.encodeWithSignature( "HorizonStakingNotAuthorized(address,address,address)", - msg.sender, users.indexer, - subgraphDataServiceAddress + subgraphDataServiceAddress, + msg.sender ) ); staking.setProvisionParameters(users.indexer, subgraphDataServiceAddress, maxVerifierCut, thawingPeriod); diff --git a/packages/horizon/test/staking/provision/provision.t.sol b/packages/horizon/test/staking/provision/provision.t.sol index cabe2f25e..81ed628fd 100644 --- a/packages/horizon/test/staking/provision/provision.t.sol +++ b/packages/horizon/test/staking/provision/provision.t.sol @@ -101,9 +101,9 @@ contract HorizonStakingProvisionTest is HorizonStakingTest { vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingNotAuthorized(address,address,address)", - users.operator, users.indexer, - subgraphDataServiceAddress + subgraphDataServiceAddress, + users.operator ); vm.expectRevert(expectedError); staking.provision(users.indexer, subgraphDataServiceAddress, amount, maxVerifierCut, thawingPeriod); diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index 722ecfe59..cdcdb6237 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -58,9 +58,9 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingNotAuthorized(address,address,address)", - users.operator, users.indexer, - newDataService + newDataService, + users.operator ); vm.expectRevert(expectedError); staking.reprovision(users.indexer, subgraphDataServiceAddress, newDataService, 0); diff --git a/packages/horizon/test/staking/provision/thaw.t.sol b/packages/horizon/test/staking/provision/thaw.t.sol index bb0b3409d..3672683ba 100644 --- a/packages/horizon/test/staking/provision/thaw.t.sol +++ b/packages/horizon/test/staking/provision/thaw.t.sol @@ -49,9 +49,9 @@ contract HorizonStakingThawTest is HorizonStakingTest { vm.startPrank(users.operator); bytes memory expectedError = abi.encodeWithSignature( "HorizonStakingNotAuthorized(address,address,address)", - users.operator, users.indexer, - subgraphDataServiceAddress + subgraphDataServiceAddress, + users.operator ); vm.expectRevert(expectedError); staking.thaw(users.indexer, subgraphDataServiceAddress, amount); From fa9da60ff285080cd22c45e2b94ac83f47904994 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 4 Oct 2024 11:56:13 +0100 Subject: [PATCH 262/277] fix: apply consistent mapping order ProvisionManagerNotAuthorized (OZ_N-05) --- .../contracts/data-service/utilities/ProvisionManager.sol | 4 ++-- .../test/subgraphService/allocation/start.t.sol | 4 ++-- .../test/subgraphService/allocation/stop.t.sol | 4 ++-- .../test/subgraphService/collect/query/query.t.sol | 4 ++-- .../test/subgraphService/provider/register.t.sol | 4 ++-- .../test/subgraphService/provision/accept.t.sol | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 845c1bdf6..02a51e4b6 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -79,7 +79,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa * @param caller The address of the caller. * @param serviceProvider The address of the service provider. */ - error ProvisionManagerNotAuthorized(address caller, address serviceProvider); + error ProvisionManagerNotAuthorized(address serviceProvider, address caller); /** * @notice Thrown when a provision is not found. @@ -93,7 +93,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa modifier onlyAuthorizedForProvision(address serviceProvider) { require( _graphStaking().isAuthorized(msg.sender, serviceProvider, address(this)), - ProvisionManagerNotAuthorized(msg.sender, serviceProvider) + ProvisionManagerNotAuthorized(serviceProvider, msg.sender) ); _; } diff --git a/packages/subgraph-service/test/subgraphService/allocation/start.t.sol b/packages/subgraph-service/test/subgraphService/allocation/start.t.sol index 9157444fb..f5d76a350 100644 --- a/packages/subgraph-service/test/subgraphService/allocation/start.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/start.t.sol @@ -60,8 +60,8 @@ contract SubgraphServiceAllocationStartTest is SubgraphServiceTest { bytes memory data = _generateData(tokens); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer + users.indexer, + users.operator )); subgraphService.startService(users.indexer, data); } diff --git a/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol b/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol index ee5958115..8a2b2a284 100644 --- a/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol +++ b/packages/subgraph-service/test/subgraphService/allocation/stop.t.sol @@ -49,8 +49,8 @@ contract SubgraphServiceAllocationStopTest is SubgraphServiceTest { vm.expectRevert( abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer + users.indexer, + users.operator ) ); subgraphService.stopService(users.indexer, data); diff --git a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol index 6ad7b5347..7f57f06f8 100644 --- a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol @@ -112,8 +112,8 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { vm.expectRevert( abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer + users.indexer, + users.operator ) ); subgraphService.collect(users.indexer, paymentType, data); diff --git a/packages/subgraph-service/test/subgraphService/provider/register.t.sol b/packages/subgraph-service/test/subgraphService/provider/register.t.sol index 1df1f5571..6a4a36737 100644 --- a/packages/subgraph-service/test/subgraphService/provider/register.t.sol +++ b/packages/subgraph-service/test/subgraphService/provider/register.t.sol @@ -41,8 +41,8 @@ contract SubgraphServiceProviderRegisterTest is SubgraphServiceTest { resetPrank(users.operator); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer + users.indexer, + users.operator )); bytes memory data = abi.encode("url", "geoHash", users.rewardsDestination); subgraphService.register(users.indexer, data); diff --git a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol index 812a27639..f89cb307e 100644 --- a/packages/subgraph-service/test/subgraphService/provision/accept.t.sol +++ b/packages/subgraph-service/test/subgraphService/provision/accept.t.sol @@ -47,8 +47,8 @@ contract SubgraphServiceProvisionAcceptTest is SubgraphServiceTest { resetPrank(users.operator); vm.expectRevert(abi.encodeWithSelector( ProvisionManager.ProvisionManagerNotAuthorized.selector, - users.operator, - users.indexer + users.indexer, + users.operator )); subgraphService.acceptProvisionPendingParameters(users.indexer, ""); } From b75154c6971d037ac8a828e40b5d572afb7d5c2a Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 4 Oct 2024 11:58:06 +0100 Subject: [PATCH 263/277] fix: apply consistent mapping order isAuthorized (OZ_N-05) --- .../contracts/interfaces/internal/IHorizonStakingMain.sol | 4 ++-- packages/horizon/contracts/staking/HorizonStaking.sol | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 002f9e9b3..f4fbe733b 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -912,10 +912,10 @@ interface IHorizonStakingMain { /** * @notice Check if an operator is authorized for the caller on a specific verifier / data service. - * @param operator The address to check for auth * @param serviceProvider The service provider on behalf of whom they're claiming to act * @param verifier The verifier / data service on which they're claiming to act + * @param operator The address to check for auth * @return Whether the operator is authorized or not */ - function isAuthorized(address operator, address serviceProvider, address verifier) external view returns (bool); + function isAuthorized(address serviceProvider, address verifier, address operator) external view returns (bool); } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index b6009043a..e838f3cf3 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -522,9 +522,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice See {IHorizonStakingMain-isAuthorized}. */ function isAuthorized( - address operator, address serviceProvider, - address verifier + address verifier, + address operator ) external view override returns (bool) { return _isAuthorized(operator, serviceProvider, verifier); } From cc14383bd5420bfd8ba7d6adc689f7d91375084a Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 4 Oct 2024 11:59:25 +0100 Subject: [PATCH 264/277] fix: apply consistent mapping order _isAuthorized (OZ_N-05) --- packages/horizon/contracts/staking/HorizonStaking.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index e838f3cf3..3f9653f95 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -47,7 +47,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { */ modifier onlyAuthorized(address serviceProvider, address verifier) { require( - _isAuthorized(msg.sender, serviceProvider, verifier), + _isAuthorized(serviceProvider, verifier, msg.sender), HorizonStakingNotAuthorized(serviceProvider, verifier, msg.sender) ); _; @@ -526,7 +526,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address verifier, address operator ) external view override returns (bool) { - return _isAuthorized(operator, serviceProvider, verifier); + return _isAuthorized(serviceProvider, verifier, operator); } /* @@ -975,7 +975,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @dev Note that this function handles the special case where the verifier is the subgraph data service, * where the operator settings are stored in the legacy mapping. */ - function _isAuthorized(address _operator, address _serviceProvider, address _verifier) private view returns (bool) { + function _isAuthorized(address _serviceProvider, address _verifier, address _operator) private view returns (bool) { if (_operator == _serviceProvider) { return true; } From 6af9e66f55d1bd680c61e3056c50decfa19671ee Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 4 Oct 2024 15:17:03 +0100 Subject: [PATCH 265/277] fix: apply consistent mapping order isAuthorized (OZ_N-05) --- .../contracts/data-service/utilities/ProvisionManager.sol | 2 +- .../shared/horizon-staking/HorizonStakingShared.t.sol | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 02a51e4b6..3b3ebd356 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -92,7 +92,7 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa */ modifier onlyAuthorizedForProvision(address serviceProvider) { require( - _graphStaking().isAuthorized(msg.sender, serviceProvider, address(this)), + _graphStaking().isAuthorized(serviceProvider, address(this), msg.sender), ProvisionManagerNotAuthorized(serviceProvider, msg.sender) ); _; diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index f9796cf94..d0c46a8dc 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -753,7 +753,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { // before bool beforeOperatorAllowed = _getStorage_OperatorAuth(msgSender, operator, verifier, legacy); - bool beforeOperatorAllowedGetter = staking.isAuthorized(operator, msgSender, verifier); + bool beforeOperatorAllowedGetter = staking.isAuthorized(msgSender, verifier, operator); assertEq(beforeOperatorAllowed, beforeOperatorAllowedGetter); // setOperator @@ -767,7 +767,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { // after bool afterOperatorAllowed = _getStorage_OperatorAuth(msgSender, operator, verifier, legacy); - bool afterOperatorAllowedGetter = staking.isAuthorized(operator, msgSender, verifier); + bool afterOperatorAllowedGetter = staking.isAuthorized(msgSender, verifier, operator); assertEq(afterOperatorAllowed, afterOperatorAllowedGetter); // assert @@ -1390,9 +1390,9 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { ); bool isAuth = staking.isAuthorized( - msgSender, beforeValues.allocation.indexer, - subgraphDataServiceLegacyAddress + subgraphDataServiceLegacyAddress, + msgSender ); address rewardsDestination = _getStorage_RewardsDestination(beforeValues.allocation.indexer); From ac965cda0c212f936ce380937341eb9c56ec2634 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Thu, 3 Oct 2024 13:24:00 +0100 Subject: [PATCH 266/277] fix: apply consistent mapping order _operatorAuth (OZ_N-05) --- packages/horizon/contracts/staking/HorizonStaking.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 3f9653f95..157a65a26 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -967,7 +967,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } else { _operatorAuth[msg.sender][_verifier][_operator] = _allowed; } - emit OperatorSet(msg.sender, _operator, _verifier, _allowed); + emit OperatorSet(msg.sender, _verifier, _operator, _allowed); } /** From 68157c0e1a21a63ab5ea978ae5c79ded52ccebbb Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Fri, 4 Oct 2024 16:30:51 +0100 Subject: [PATCH 267/277] fix: swap peram order _getStorage_OperatorAuth --- .../horizon-staking/HorizonStakingShared.t.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index d0c46a8dc..4adf6fcd4 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -752,7 +752,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { bool legacy = verifier == subgraphDataServiceLegacyAddress; // before - bool beforeOperatorAllowed = _getStorage_OperatorAuth(msgSender, operator, verifier, legacy); + bool beforeOperatorAllowed = _getStorage_OperatorAuth(msgSender, verifier, operator, legacy); bool beforeOperatorAllowedGetter = staking.isAuthorized(msgSender, verifier, operator); assertEq(beforeOperatorAllowed, beforeOperatorAllowedGetter); @@ -766,9 +766,9 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { } // after - bool afterOperatorAllowed = _getStorage_OperatorAuth(msgSender, operator, verifier, legacy); + bool afterOperatorAllowed = _getStorage_OperatorAuth(msgSender, verifier, operator, legacy); bool afterOperatorAllowedGetter = staking.isAuthorized(msgSender, verifier, operator); - assertEq(afterOperatorAllowed, afterOperatorAllowedGetter); + assertEq(afterOperatorAllowed, afterOperatorAllowedGetter, "afterOperatorAllowedGetter FAIL"); // assert assertEq(afterOperatorAllowed, allow); @@ -1686,8 +1686,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { function _getStorage_OperatorAuth( address serviceProvider, - address operator, address verifier, + address operator, bool legacy ) internal view returns (bool) { uint256 slotNumber = legacy ? 21 : 31; @@ -1699,8 +1699,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { slot = uint256( keccak256( abi.encode( - operator, - keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, slotNumber)))) + verifier, + keccak256(abi.encode(operator, keccak256(abi.encode(serviceProvider, slotNumber)))) ) ) ); From 1693d7650192cf5490a5168be4dcdf9956e51ad8 Mon Sep 17 00:00:00 2001 From: MoonBoi9001 Date: Mon, 7 Oct 2024 13:19:57 +0100 Subject: [PATCH 268/277] fix: set new peram order various functions (OZ_N-05) --- .../internal/IHorizonStakingMain.sol | 12 +++++----- .../contracts/staking/HorizonStaking.sol | 10 ++++----- .../HorizonStakingShared.t.sol | 22 +++++++++---------- .../test/staking/operator/locked.t.sol | 8 +++---- .../test/staking/operator/operator.t.sol | 8 +++---- .../test/staking/provision/locked.t.sol | 4 ++-- .../test/staking/provision/reprovision.t.sol | 2 +- .../serviceProvider/serviceProvider.t.sol | 2 +- .../subgraphService/SubgraphService.t.sol | 2 +- 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index f4fbe733b..b6a787138 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -108,14 +108,14 @@ interface IHorizonStakingMain { /** * @dev Emitted when an operator is allowed or denied by a service provider for a particular verifier * @param serviceProvider The address of the service provider - * @param operator The address of the operator * @param verifier The address of the verifier + * @param operator The address of the operator * @param allowed Whether the operator is allowed or denied */ event OperatorSet( address indexed serviceProvider, - address indexed operator, address indexed verifier, + address indexed operator, bool allowed ); @@ -865,11 +865,11 @@ interface IHorizonStakingMain { * Additional requirements: * - The `verifier` must be allowed to be used for locked provisions. * - * @param operator Address to authorize or unauthorize * @param verifier The verifier / data service on which they'll be allowed to operate + * @param operator Address to authorize or unauthorize * @param allowed Whether the operator is authorized or not */ - function setOperatorLocked(address operator, address verifier, bool allowed) external; + function setOperatorLocked(address verifier, address operator, bool allowed) external; /** * @notice Sets a verifier as a globally allowed verifier for locked provisions. @@ -904,11 +904,11 @@ interface IHorizonStakingMain { /** * @notice Authorize or unauthorize an address to be an operator for the caller on a data service. * @dev Emits a {OperatorSet} event. - * @param operator Address to authorize or unauthorize * @param verifier The verifier / data service on which they'll be allowed to operate + * @param operator Address to authorize or unauthorize * @param allowed Whether the operator is authorized or not */ - function setOperator(address operator, address verifier, bool allowed) external; + function setOperator(address verifier, address operator, bool allowed) external; /** * @notice Check if an operator is authorized for the caller on a specific verifier / data service. diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 157a65a26..8f3fb524a 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -466,9 +466,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice See {IHorizonStakingMain-setOperatorLocked}. */ - function setOperatorLocked(address operator, address verifier, bool allowed) external override notPaused { + function setOperatorLocked(address verifier, address operator, bool allowed) external override notPaused { require(_allowedLockedVerifiers[verifier], HorizonStakingVerifierNotAllowed(verifier)); - _setOperator(operator, verifier, allowed); + _setOperator(verifier, operator, allowed); } /* @@ -514,8 +514,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice See {IHorizonStakingMain-setOperator}. */ - function setOperator(address operator, address verifier, bool allowed) external override notPaused { - _setOperator(operator, verifier, allowed); + function setOperator(address verifier, address operator, bool allowed) external override notPaused { + _setOperator(verifier, operator, allowed); } /** @@ -960,7 +960,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @dev Note that this function handles the special case where the verifier is the subgraph data service, * where the operator settings are stored in the legacy mapping. */ - function _setOperator(address _operator, address _verifier, bool _allowed) private { + function _setOperator(address _verifier, address _operator, bool _allowed) private { require(_operator != msg.sender, HorizonStakingCallerIsServiceProvider()); if (_verifier == SUBGRAPH_DATA_SERVICE_ADDRESS) { _legacyOperatorAuth[msg.sender][_operator] = _allowed; diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 4adf6fcd4..b13128c72 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -41,7 +41,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { modifier useOperator() { vm.startPrank(users.indexer); - _setOperator(users.operator, subgraphDataServiceAddress, true); + _setOperator(subgraphDataServiceAddress, users.operator, true); vm.startPrank(users.operator); _; vm.stopPrank(); @@ -736,15 +736,15 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.createdAt, beforeProvision.createdAt); } - function _setOperator(address operator, address verifier, bool allow) internal { - __setOperator(operator, verifier, allow, false); + function _setOperator(address verifier, address operator, bool allow) internal { + __setOperator(verifier, operator, allow, false); } - function _setOperatorLocked(address operator, address verifier, bool allow) internal { - __setOperator(operator, verifier, allow, true); + function _setOperatorLocked(address verifier, address operator, bool allow) internal { + __setOperator(verifier, operator, allow, true); } - function __setOperator(address operator, address verifier, bool allow, bool locked) private { + function __setOperator(address verifier, address operator, bool allow, bool locked) private { (, address msgSender, ) = vm.readCallers(); // staking contract knows the address of the legacy subgraph service @@ -758,11 +758,11 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { // setOperator vm.expectEmit(address(staking)); - emit IHorizonStakingMain.OperatorSet(msgSender, operator, verifier, allow); + emit IHorizonStakingMain.OperatorSet(msgSender, verifier, operator, allow); if (locked) { - staking.setOperatorLocked(operator, verifier, allow); + staking.setOperatorLocked(verifier, operator, allow); } else { - staking.setOperator(operator, verifier, allow); + staking.setOperator(verifier, operator, allow); } // after @@ -1699,8 +1699,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { slot = uint256( keccak256( abi.encode( - verifier, - keccak256(abi.encode(operator, keccak256(abi.encode(serviceProvider, slotNumber)))) + operator, + keccak256(abi.encode(verifier, keccak256(abi.encode(serviceProvider, slotNumber)))) ) ) ); diff --git a/packages/horizon/test/staking/operator/locked.t.sol b/packages/horizon/test/staking/operator/locked.t.sol index 706b47a07..3d9b5f1e6 100644 --- a/packages/horizon/test/staking/operator/locked.t.sol +++ b/packages/horizon/test/staking/operator/locked.t.sol @@ -12,22 +12,22 @@ contract HorizonStakingOperatorLockedTest is HorizonStakingTest { */ function testOperatorLocked_Set() public useIndexer useLockedVerifier(subgraphDataServiceAddress) { - _setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + _setOperatorLocked(subgraphDataServiceAddress, users.operator, true); } function testOperatorLocked_RevertWhen_VerifierNotAllowed() public useIndexer { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingVerifierNotAllowed(address)", subgraphDataServiceAddress); vm.expectRevert(expectedError); - staking.setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + staking.setOperatorLocked(subgraphDataServiceAddress, users.operator, true); } function testOperatorLocked_RevertWhen_CallerIsServiceProvider() public useIndexer useLockedVerifier(subgraphDataServiceAddress) { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCallerIsServiceProvider()"); vm.expectRevert(expectedError); - staking.setOperatorLocked(users.indexer, subgraphDataServiceAddress, true); + staking.setOperatorLocked(subgraphDataServiceAddress, users.indexer, true); } function testOperatorLocked_SetLegacySubgraphService() public useIndexer useLockedVerifier(subgraphDataServiceLegacyAddress) { - _setOperatorLocked(users.operator, subgraphDataServiceLegacyAddress, true); + _setOperatorLocked(subgraphDataServiceLegacyAddress, users.operator, true); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/operator/operator.t.sol b/packages/horizon/test/staking/operator/operator.t.sol index 5d509ba68..a821e561d 100644 --- a/packages/horizon/test/staking/operator/operator.t.sol +++ b/packages/horizon/test/staking/operator/operator.t.sol @@ -12,17 +12,17 @@ contract HorizonStakingOperatorTest is HorizonStakingTest { */ function testOperator_SetOperator() public useIndexer { - _setOperator(users.operator, subgraphDataServiceAddress, true); + _setOperator(subgraphDataServiceAddress, users.operator, true); } function testOperator_RevertWhen_CallerIsServiceProvider() public useIndexer { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingCallerIsServiceProvider()"); vm.expectRevert(expectedError); - staking.setOperator(users.indexer, subgraphDataServiceAddress, true); + staking.setOperator(subgraphDataServiceAddress, users.indexer, true); } function testOperator_RemoveOperator() public useIndexer { - _setOperator(users.operator, subgraphDataServiceAddress, true); - _setOperator(users.operator, subgraphDataServiceAddress, false); + _setOperator(subgraphDataServiceAddress, users.operator, true); + _setOperator(subgraphDataServiceAddress, users.operator, false); } } \ No newline at end of file diff --git a/packages/horizon/test/staking/provision/locked.t.sol b/packages/horizon/test/staking/provision/locked.t.sol index 66745839b..2dcae964a 100644 --- a/packages/horizon/test/staking/provision/locked.t.sol +++ b/packages/horizon/test/staking/provision/locked.t.sol @@ -17,7 +17,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { uint256 provisionTokens = staking.getProviderTokensAvailable(users.indexer, subgraphDataServiceAddress); assertEq(provisionTokens, 0); - _setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + _setOperatorLocked(subgraphDataServiceAddress, users.operator, true); vm.startPrank(users.operator); _provisionLocked( @@ -39,7 +39,7 @@ contract HorizonStakingProvisionLockedTest is HorizonStakingTest { assertEq(provisionTokens, 0); // Set operator - _setOperatorLocked(users.operator, subgraphDataServiceAddress, true); + _setOperatorLocked(subgraphDataServiceAddress, users.operator, true); // Disable locked verifier vm.startPrank(users.governor); diff --git a/packages/horizon/test/staking/provision/reprovision.t.sol b/packages/horizon/test/staking/provision/reprovision.t.sol index cdcdb6237..be650019f 100644 --- a/packages/horizon/test/staking/provision/reprovision.t.sol +++ b/packages/horizon/test/staking/provision/reprovision.t.sol @@ -37,7 +37,7 @@ contract HorizonStakingReprovisionTest is HorizonStakingTest { // Switch to indexer to set operator for new data service vm.startPrank(users.indexer); - _setOperator(users.operator, newDataService, true); + _setOperator(newDataService, users.operator, true); // Switch back to operator vm.startPrank(users.operator); diff --git a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol index 7db480869..9f4893942 100644 --- a/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol +++ b/packages/horizon/test/staking/serviceProvider/serviceProvider.t.sol @@ -25,7 +25,7 @@ contract HorizonStakingServiceProviderTest is HorizonStakingTest { assertEq(sp.tokensStaked, amount); assertEq(sp.tokensProvisioned, amount); - _setOperator(users.operator, subgraphDataServiceAddress, true); + _setOperator(subgraphDataServiceAddress, users.operator, true); resetPrank(users.operator); _stakeTo(users.indexer, operatorAmount); sp = staking.getServiceProvider(users.indexer); diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index ce9810d81..013f869a8 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -39,7 +39,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { modifier useOperator() { resetPrank(users.indexer); - staking.setOperator(users.operator, address(subgraphService), true); + staking.setOperator(address(subgraphService), users.operator, true); resetPrank(users.operator); _; vm.stopPrank(); From 0f1522d58427e292aa8d596b8657e2c303a63f7d Mon Sep 17 00:00:00 2001 From: MoonBoi9001 <67825802+MoonBoi9001@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:34:20 +0100 Subject: [PATCH 269/277] Update packages/horizon/contracts/data-service/utilities/ProvisionManager.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomás Migone --- .../contracts/data-service/utilities/ProvisionManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol index 3b3ebd356..a3f96794c 100644 --- a/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol +++ b/packages/horizon/contracts/data-service/utilities/ProvisionManager.sol @@ -76,8 +76,8 @@ abstract contract ProvisionManager is Initializable, GraphDirectory, ProvisionMa /** * @notice Thrown when the caller is not authorized to manage the provision of a service provider. + * @param serviceProvider The address of the serviceProvider. * @param caller The address of the caller. - * @param serviceProvider The address of the service provider. */ error ProvisionManagerNotAuthorized(address serviceProvider, address caller); From a76a0d6bcf1ef25c11ddaa15d9616e6a33e38840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 8 Oct 2024 13:02:37 -0300 Subject: [PATCH 270/277] feat: separate escrow accounts for each collector (#1058) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: separate escrow accounts for each collector Signed-off-by: Tomás Migone * feat: escrow account per collector Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone --- .../contracts/interfaces/IPaymentsEscrow.sol | 61 ++++++++++++------- .../contracts/payments/PaymentsEscrow.sol | 49 ++++++++------- .../horizon/test/escrow/GraphEscrow.t.sol | 4 +- packages/horizon/test/escrow/collect.t.sol | 14 ++--- packages/horizon/test/escrow/deposit.t.sol | 2 +- packages/horizon/test/escrow/paused.t.sol | 8 +-- packages/horizon/test/escrow/thaw.t.sol | 16 ++--- packages/horizon/test/escrow/withdraw.t.sol | 8 +-- .../subgraphService/collect/query/query.t.sol | 2 +- 9 files changed, 91 insertions(+), 73 deletions(-) diff --git a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol index b480f3c31..c1eb7707a 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsEscrow.sol @@ -15,9 +15,9 @@ import { IGraphPayments } from "./IGraphPayments.sol"; * collector contract which implements the {IPaymentsCollector} interface. */ interface IPaymentsEscrow { - /// @notice Escrow account for a payer-receiver pair + /// @notice Escrow account for a payer-collector-receiver tuple struct EscrowAccount { - // Total token balance for the payer-receiver pair + // Total token balance for the payer-collector-receiver tuple uint256 balance; // Amount of tokens currently being thawed uint256 tokensThawing; @@ -70,12 +70,13 @@ interface IPaymentsEscrow { event RevokeCollector(address indexed payer, address indexed collector); /** - * @notice Emitted when a payer deposits funds into the escrow for a payer-receiver pair + * @notice Emitted when a payer deposits funds into the escrow for a payer-collector-receiver tuple * @param payer The address of the payer + * @param collector The address of the collector * @param receiver The address of the receiver * @param tokens The amount of tokens deposited */ - event Deposit(address indexed payer, address indexed receiver, uint256 tokens); + event Deposit(address indexed payer, address indexed collector, address indexed receiver, uint256 tokens); /** * @notice Emitted when a payer cancels an escrow thawing @@ -85,29 +86,38 @@ interface IPaymentsEscrow { event CancelThaw(address indexed payer, address indexed receiver); /** - * @notice Emitted when a payer thaws funds from the escrow for a payer-receiver pair + * @notice Emitted when a payer thaws funds from the escrow for a payer-collector-receiver tuple * @param payer The address of the payer + * @param collector The address of the collector * @param receiver The address of the receiver * @param tokens The amount of tokens being thawed * @param thawEndTimestamp The timestamp at which the thawing period ends */ - event Thaw(address indexed payer, address indexed receiver, uint256 tokens, uint256 thawEndTimestamp); + event Thaw( + address indexed payer, + address indexed collector, + address indexed receiver, + uint256 tokens, + uint256 thawEndTimestamp + ); /** - * @notice Emitted when a payer withdraws funds from the escrow for a payer-receiver pair + * @notice Emitted when a payer withdraws funds from the escrow for a payer-collector-receiver tuple * @param payer The address of the payer + * @param collector The address of the collector * @param receiver The address of the receiver * @param tokens The amount of tokens withdrawn */ - event Withdraw(address indexed payer, address indexed receiver, uint256 tokens); + event Withdraw(address indexed payer, address indexed collector, address indexed receiver, uint256 tokens); /** - * @notice Emitted when a collector collects funds from the escrow for a payer-receiver pair + * @notice Emitted when a collector collects funds from the escrow for a payer-collector-receiver tuple * @param payer The address of the payer + * @param collector The address of the collector * @param receiver The address of the receiver * @param tokens The amount of tokens collected */ - event EscrowCollected(address indexed payer, address indexed receiver, uint256 tokens); + event EscrowCollected(address indexed payer, address indexed collector, address indexed receiver, uint256 tokens); // -- Errors -- @@ -211,26 +221,28 @@ interface IPaymentsEscrow { function revokeCollector(address collector) external; /** - * @notice Deposits funds into the escrow for a payer-receiver pair, where + * @notice Deposits funds into the escrow for a payer-collector-receiver tuple, where * the payer is the transaction caller. * @dev Emits a {Deposit} event + * @param collector The address of the collector * @param receiver The address of the receiver * @param tokens The amount of tokens to deposit */ - function deposit(address receiver, uint256 tokens) external; + function deposit(address collector, address receiver, uint256 tokens) external; /** - * @notice Deposits funds into the escrow for a payer-receiver pair, where + * @notice Deposits funds into the escrow for a payer-collector-receiver tuple, where * the payer can be specified. * @dev Emits a {Deposit} event * @param payer The address of the payer + * @param collector The address of the collector * @param receiver The address of the receiver * @param tokens The amount of tokens to deposit */ - function depositTo(address payer, address receiver, uint256 tokens) external; + function depositTo(address payer, address collector, address receiver, uint256 tokens) external; /** - * @notice Thaw a specific amount of escrow from a payer-receiver's escrow account. + * @notice Thaw a specific amount of escrow from a payer-collector-receiver's escrow account. * The payer is the transaction caller. * If `tokens` is zero and funds were already thawing it will cancel the thawing. * Note that repeated calls to this function will overwrite the previous thawing amount @@ -240,13 +252,14 @@ interface IPaymentsEscrow { * * Emits a {Thaw} event. If `tokens` is zero it will emit a {CancelThaw} event. * + * @param collector The address of the collector * @param receiver The address of the receiver * @param tokens The amount of tokens to thaw */ - function thaw(address receiver, uint256 tokens) external; + function thaw(address collector, address receiver, uint256 tokens) external; /** - * @notice Withdraws all thawed escrow from a payer-receiver's escrow account. + * @notice Withdraws all thawed escrow from a payer-collector-receiver's escrow account. * The payer is the transaction caller. * Note that the withdrawn funds might be less than the thawed amount if there were * payment collections in the meantime. @@ -255,12 +268,13 @@ interface IPaymentsEscrow { * * Emits a {Withdraw} event * + * @param collector The address of the collector * @param receiver The address of the receiver */ - function withdraw(address receiver) external; + function withdraw(address collector, address receiver) external; /** - * @notice Collects funds from the payer-receiver's escrow and sends them to {GraphPayments} for + * @notice Collects funds from the payer-collector-receiver's escrow and sends them to {GraphPayments} for * distribution using the Graph Horizon Payments protocol. * The function will revert if there are not enough funds in the escrow. * @dev Requirements: @@ -272,7 +286,7 @@ interface IPaymentsEscrow { * @param payer The address of the payer * @param receiver The address of the receiver * @param tokens The amount of tokens to collect - * @param collector The address of the collector + * @param dataService The address of the data service * @param tokensDataService The amount of tokens that {GraphPayments} should send to the data service */ function collect( @@ -280,14 +294,15 @@ interface IPaymentsEscrow { address payer, address receiver, uint256 tokens, - address collector, + address dataService, uint256 tokensDataService ) external; /** - * @notice Get the balance of a payer-receiver pair + * @notice Get the balance of a payer-collector-receiver tuple * @param payer The address of the payer + * @param collector The address of the collector * @param receiver The address of the receiver */ - function getBalance(address payer, address receiver) external view returns (uint256); + function getBalance(address payer, address collector, address receiver) external view returns (uint256); } diff --git a/packages/horizon/contracts/payments/PaymentsEscrow.sol b/packages/horizon/contracts/payments/PaymentsEscrow.sol index bd6bd0ad1..7cf7e9e38 100644 --- a/packages/horizon/contracts/payments/PaymentsEscrow.sol +++ b/packages/horizon/contracts/payments/PaymentsEscrow.sol @@ -27,11 +27,11 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, mapping(address payer => mapping(address collector => IPaymentsEscrow.Collector collectorDetails)) public authorizedCollectors; - /// @notice Escrow account details for payer-receiver pairs - mapping(address payer => mapping(address receiver => IPaymentsEscrow.EscrowAccount escrowAccount)) + /// @notice Escrow account details for payer-collector-receiver tuples + mapping(address payer => mapping(address collector => mapping(address receiver => IPaymentsEscrow.EscrowAccount escrowAccount))) public escrowAccounts; - /// @notice The maximum thawing period (in seconds) for both escrow withdrawal and signer revocation + /// @notice The maximum thawing period (in seconds) for both escrow withdrawal and collector revocation /// @dev This is a precautionary measure to avoid inadvertedly locking funds for too long uint256 public constant MAX_WAIT_PERIOD = 90 days; @@ -126,22 +126,22 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, /** * @notice See {IPaymentsEscrow-deposit} */ - function deposit(address receiver, uint256 tokens) external override notPaused { - _deposit(msg.sender, receiver, tokens); + function deposit(address collector, address receiver, uint256 tokens) external override notPaused { + _deposit(msg.sender, collector, receiver, tokens); } /** * @notice See {IPaymentsEscrow-depositTo} */ - function depositTo(address payer, address receiver, uint256 tokens) external override notPaused { - _deposit(payer, receiver, tokens); + function depositTo(address payer, address collector, address receiver, uint256 tokens) external override notPaused { + _deposit(payer, collector, receiver, tokens); } /** * @notice See {IPaymentsEscrow-thaw} */ - function thaw(address receiver, uint256 tokens) external override notPaused { - EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; + function thaw(address collector, address receiver, uint256 tokens) external override notPaused { + EscrowAccount storage account = escrowAccounts[msg.sender][collector][receiver]; // if amount thawing is zero and requested amount is zero this is an invalid request. // otherwise if amount thawing is greater than zero and requested amount is zero this @@ -159,14 +159,14 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, account.tokensThawing = tokens; account.thawEndTimestamp = block.timestamp + WITHDRAW_ESCROW_THAWING_PERIOD; - emit Thaw(msg.sender, receiver, tokens, account.thawEndTimestamp); + emit Thaw(msg.sender, collector, receiver, tokens, account.thawEndTimestamp); } /** * @notice See {IPaymentsEscrow-withdraw} */ - function withdraw(address receiver) external override notPaused { - EscrowAccount storage account = escrowAccounts[msg.sender][receiver]; + function withdraw(address collector, address receiver) external override notPaused { + EscrowAccount storage account = escrowAccounts[msg.sender][collector][receiver]; require(account.thawEndTimestamp != 0, PaymentsEscrowNotThawing()); require( account.thawEndTimestamp < block.timestamp, @@ -180,7 +180,7 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, account.tokensThawing = 0; account.thawEndTimestamp = 0; _graphToken().pushTokens(msg.sender, tokens); - emit Withdraw(msg.sender, receiver, tokens); + emit Withdraw(msg.sender, collector, receiver, tokens); } /** @@ -195,15 +195,18 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, uint256 tokensDataService ) external override notPaused { // Check if collector is authorized and has enough funds - Collector storage collector = authorizedCollectors[payer][msg.sender]; - require(collector.allowance >= tokens, PaymentsEscrowInsufficientAllowance(collector.allowance, tokens)); + Collector storage collectorDetails = authorizedCollectors[payer][msg.sender]; + require( + collectorDetails.allowance >= tokens, + PaymentsEscrowInsufficientAllowance(collectorDetails.allowance, tokens) + ); // Check if there are enough funds in the escrow account - EscrowAccount storage account = escrowAccounts[payer][receiver]; + EscrowAccount storage account = escrowAccounts[payer][msg.sender][receiver]; require(account.balance >= tokens, PaymentsEscrowInsufficientBalance(account.balance, tokens)); // Reduce amount from approved collector and account balance - collector.allowance -= tokens; + collectorDetails.allowance -= tokens; account.balance -= tokens; uint256 balanceBefore = _graphToken().balanceOf(address(this)); @@ -217,14 +220,14 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, PaymentsEscrowInconsistentCollection(balanceBefore, balanceAfter, tokens) ); - emit EscrowCollected(payer, receiver, tokens); + emit EscrowCollected(payer, msg.sender, receiver, tokens); } /** * @notice See {IPaymentsEscrow-getBalance} */ - function getBalance(address payer, address receiver) external view override returns (uint256) { - EscrowAccount storage account = escrowAccounts[payer][receiver]; + function getBalance(address payer, address collector, address receiver) external view override returns (uint256) { + EscrowAccount storage account = escrowAccounts[payer][collector][receiver]; return account.balance - account.tokensThawing; } @@ -234,9 +237,9 @@ contract PaymentsEscrow is Initializable, MulticallUpgradeable, GraphDirectory, * @param _receiver The address of the receiver * @param _tokens The amount of tokens to deposit */ - function _deposit(address _payer, address _receiver, uint256 _tokens) private { - escrowAccounts[_payer][_receiver].balance += _tokens; + function _deposit(address _payer, address _collector, address _receiver, uint256 _tokens) private { + escrowAccounts[_payer][_collector][_receiver].balance += _tokens; _graphToken().pullTokens(msg.sender, _tokens); - emit Deposit(_payer, _receiver, _tokens); + emit Deposit(_payer, _collector, _receiver, _tokens); } } diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index 2421ea80c..75d0b55ae 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -39,7 +39,7 @@ contract GraphEscrowTest is HorizonStakingSharedTest { vm.assume(thawAmount > 0); vm.assume(amount > thawAmount); _depositTokens(amount); - escrow.thaw(users.indexer, thawAmount); + escrow.thaw(users.verifier, users.indexer, thawAmount); _; } @@ -49,7 +49,7 @@ contract GraphEscrowTest is HorizonStakingSharedTest { function _depositTokens(uint256 tokens) internal { token.approve(address(escrow), tokens); - escrow.deposit(users.indexer, tokens); + escrow.deposit(users.verifier, users.indexer, tokens); } function _approveEscrow(uint256 tokens) internal { diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index d9b775b93..db0c2c099 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -27,8 +27,10 @@ contract GraphEscrowCollectTest is GraphEscrowTest { address _dataService, uint256 _tokensDataService ) private { + (, address _collector, ) = vm.readCallers(); + // Previous balances - (uint256 previousPayerEscrowBalance,,) = escrow.escrowAccounts(_payer, _receiver); + (uint256 previousPayerEscrowBalance,,) = escrow.escrowAccounts(_payer, _collector, _receiver); CollectPaymentData memory previousBalances = CollectPaymentData({ escrowBalance: token.balanceOf(address(escrow)), paymentsBalance: token.balanceOf(address(payments)), @@ -41,7 +43,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { }); vm.expectEmit(address(escrow)); - emit IPaymentsEscrow.EscrowCollected(_payer, _receiver, _tokens); + emit IPaymentsEscrow.EscrowCollected(_payer, _collector, _receiver, _tokens); escrow.collect(_paymentType, _payer, _receiver, _tokens, _dataService, _tokensDataService); // Calculate cuts @@ -51,11 +53,9 @@ contract GraphEscrowCollectTest is GraphEscrowTest { _dataService, _paymentType ); - uint256 tokensProtocol = _tokens * protocolPaymentCut / MAX_PPM; - uint256 tokensDelegation = _tokens * delegatorCut / MAX_PPM; // After balances - (uint256 afterPayerEscrowBalance,,) = escrow.escrowAccounts(_payer, _receiver); + (uint256 afterPayerEscrowBalance,,) = escrow.escrowAccounts(_payer, _collector, _receiver); CollectPaymentData memory afterBalances = CollectPaymentData({ escrowBalance: token.balanceOf(address(escrow)), paymentsBalance: token.balanceOf(address(payments)), @@ -68,12 +68,12 @@ contract GraphEscrowCollectTest is GraphEscrowTest { }); // Check receiver balance after payment - uint256 receiverExpectedPayment = _tokens - _tokensDataService - tokensProtocol - tokensDelegation; + uint256 receiverExpectedPayment = _tokens - _tokensDataService - _tokens * protocolPaymentCut / MAX_PPM - _tokens * delegatorCut / MAX_PPM; assertEq(afterBalances.receiverBalance - previousBalances.receiverBalance, receiverExpectedPayment); assertEq(token.balanceOf(address(payments)), 0); // Check delegation pool balance after payment - assertEq(afterBalances.delegationPoolBalance - previousBalances.delegationPoolBalance, tokensDelegation); + assertEq(afterBalances.delegationPoolBalance - previousBalances.delegationPoolBalance, _tokens * delegatorCut / MAX_PPM); // Check that the escrow account has been updated assertEq(previousBalances.escrowBalance, afterBalances.escrowBalance + _tokens); diff --git a/packages/horizon/test/escrow/deposit.t.sol b/packages/horizon/test/escrow/deposit.t.sol index 3ce341a1a..002d2b1a4 100644 --- a/packages/horizon/test/escrow/deposit.t.sol +++ b/packages/horizon/test/escrow/deposit.t.sol @@ -12,7 +12,7 @@ contract GraphEscrowDepositTest is GraphEscrowTest { */ function testDeposit_Tokens(uint256 amount) public useGateway useDeposit(amount) { - (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); + (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.verifier, users.indexer); assertEq(indexerEscrowBalance, amount); } } \ No newline at end of file diff --git a/packages/horizon/test/escrow/paused.t.sol b/packages/horizon/test/escrow/paused.t.sol index f6b65aa2b..a993da883 100644 --- a/packages/horizon/test/escrow/paused.t.sol +++ b/packages/horizon/test/escrow/paused.t.sol @@ -31,18 +31,18 @@ contract GraphEscrowPausedTest is GraphEscrowTest { function testPaused_RevertWhen_Deposit(uint256 tokens) public useGateway usePaused(true) { vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); - escrow.deposit(users.indexer, tokens); + escrow.deposit(users.verifier, users.indexer, tokens); } function testPaused_RevertWhen_DepositTo(uint256 tokens) public usePaused(true) { resetPrank(users.operator); vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); - escrow.depositTo(users.gateway, users.indexer, tokens); + escrow.depositTo(users.gateway, users.verifier, users.indexer, tokens); } function testPaused_RevertWhen_ThawTokens(uint256 tokens) public useGateway useDeposit(tokens) usePaused(true) { vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); - escrow.thaw(users.indexer, tokens); + escrow.thaw(users.verifier, users.indexer, tokens); } function testPaused_RevertWhen_WithdrawTokens( @@ -53,7 +53,7 @@ contract GraphEscrowPausedTest is GraphEscrowTest { skip(withdrawEscrowThawingPeriod + 1); vm.expectRevert(abi.encodeWithSelector(IPaymentsEscrow.PaymentsEscrowIsPaused.selector)); - escrow.withdraw(users.indexer); + escrow.withdraw(users.verifier, users.indexer); } // Collect diff --git a/packages/horizon/test/escrow/thaw.t.sol b/packages/horizon/test/escrow/thaw.t.sol index 36808602c..8e2674e00 100644 --- a/packages/horizon/test/escrow/thaw.t.sol +++ b/packages/horizon/test/escrow/thaw.t.sol @@ -16,10 +16,10 @@ contract GraphEscrowThawTest is GraphEscrowTest { function testThaw_Tokens(uint256 amount) public useGateway useDeposit(amount) { uint256 expectedThawEndTimestamp = block.timestamp + withdrawEscrowThawingPeriod; vm.expectEmit(address(escrow)); - emit IPaymentsEscrow.Thaw(users.gateway, users.indexer, amount, expectedThawEndTimestamp); - escrow.thaw(users.indexer, amount); + emit IPaymentsEscrow.Thaw(users.gateway, users.verifier, users.indexer, amount, expectedThawEndTimestamp); + escrow.thaw(users.verifier, users.indexer, amount); - (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.indexer); + (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.verifier, users.indexer); assertEq(amountThawing, amount); assertEq(thawEndTimestamp, expectedThawEndTimestamp); } @@ -29,7 +29,7 @@ contract GraphEscrowThawTest is GraphEscrowTest { ) public useGateway useDeposit(amount) { bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowNotThawing()"); vm.expectRevert(expectedError); - escrow.thaw(users.indexer, 0); + escrow.thaw(users.verifier, users.indexer, 0); } function testThaw_RevertWhen_InsufficientAmount( @@ -39,14 +39,14 @@ contract GraphEscrowThawTest is GraphEscrowTest { overAmount = bound(overAmount, amount + 1, type(uint256).max); bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowInsufficientBalance(uint256,uint256)", amount, overAmount); vm.expectRevert(expectedError); - escrow.thaw(users.indexer, overAmount); + escrow.thaw(users.verifier, users.indexer, overAmount); } function testThaw_CancelRequest(uint256 amount) public useGateway useDeposit(amount) { - escrow.thaw(users.indexer, amount); - escrow.thaw(users.indexer, 0); + escrow.thaw(users.verifier, users.indexer, amount); + escrow.thaw(users.verifier, users.indexer, 0); - (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.indexer); + (, uint256 amountThawing,uint256 thawEndTimestamp) = escrow.escrowAccounts(users.gateway, users.verifier, users.indexer); assertEq(amountThawing, 0); assertEq(thawEndTimestamp, 0); } diff --git a/packages/horizon/test/escrow/withdraw.t.sol b/packages/horizon/test/escrow/withdraw.t.sol index 0e5670c7a..a141d039b 100644 --- a/packages/horizon/test/escrow/withdraw.t.sol +++ b/packages/horizon/test/escrow/withdraw.t.sol @@ -18,17 +18,17 @@ contract GraphEscrowWithdrawTest is GraphEscrowTest { // advance time skip(withdrawEscrowThawingPeriod + 1); - escrow.withdraw(users.indexer); + escrow.withdraw(users.verifier, users.indexer); vm.stopPrank(); - (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.indexer); + (uint256 indexerEscrowBalance,,) = escrow.escrowAccounts(users.gateway, users.verifier, users.indexer); assertEq(indexerEscrowBalance, amount - thawAmount); } function testWithdraw_RevertWhen_NotThawing(uint256 amount) public useGateway useDeposit(amount) { bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowNotThawing()"); vm.expectRevert(expectedError); - escrow.withdraw(users.indexer); + escrow.withdraw(users.verifier, users.indexer); } function testWithdraw_RevertWhen_StillThawing( @@ -37,6 +37,6 @@ contract GraphEscrowWithdrawTest is GraphEscrowTest { ) public useGateway depositAndThawTokens(amount, thawAmount) { bytes memory expectedError = abi.encodeWithSignature("PaymentsEscrowStillThawing(uint256,uint256)", block.timestamp, block.timestamp + withdrawEscrowThawingPeriod); vm.expectRevert(expectedError); - escrow.withdraw(users.indexer); + escrow.withdraw(users.verifier, users.indexer); } } \ No newline at end of file diff --git a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol index 6ad7b5347..f39e6537b 100644 --- a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol @@ -53,7 +53,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { mint(signer, tokens); escrow.approveCollector(address(tapCollector), tokens); token.approve(address(escrow), tokens); - escrow.deposit(users.indexer, tokens); + escrow.deposit(address(tapCollector), users.indexer, tokens); resetPrank(msgSender); } From 70354033e076475937a53bfe7554c17900d2b6bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 9 Oct 2024 12:12:16 -0300 Subject: [PATCH 271/277] fix: tweaks to thawing pool management (#1048) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: wip tweaks to thawing pool management Signed-off-by: Tomás Migone * fix: handle edge cases for thawing pools Signed-off-by: Tomás Migone * fix: simplify some conditions and checks Signed-off-by: Tomás Migone * chore: fix test comment Signed-off-by: Tomás Migone * fix: typos and variable rename Signed-off-by: Tomás Migone * fix: merge conflicts Signed-off-by: Tomás Migone * fix: improve thawing pool reset condition Signed-off-by: Tomás Migone --------- Signed-off-by: Tomás Migone --- .../internal/IHorizonStakingMain.sol | 11 +- .../internal/IHorizonStakingTypes.sol | 8 + .../contracts/staking/HorizonStaking.sol | 125 +++++++++++--- .../contracts/staking/HorizonStakingBase.sol | 1 + .../HorizonStakingShared.t.sol | 155 ++++++++++++++---- .../test/staking/delegation/addToPool.t.sol | 61 ++++++- .../test/staking/delegation/delegate.t.sol | 41 ++++- .../test/staking/delegation/undelegate.t.sol | 116 +++++++++++-- .../test/staking/delegation/withdraw.t.sol | 108 +++++++++--- .../test/staking/provision/deprovision.t.sol | 45 +++++ .../horizon/test/staking/provision/thaw.t.sol | 41 +++++ .../horizon/test/staking/slash/slash.t.sol | 48 +++++- 12 files changed, 651 insertions(+), 109 deletions(-) diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index b6a787138..8d047ac1d 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -254,8 +254,15 @@ interface IHorizonStakingMain { * @param tokens The amount of tokens being released * @param shares The amount of shares being released * @param thawingUntil The timestamp until the stake has thawed + * @param valid Whether the thaw request was valid at the time of fulfillment */ - event ThawRequestFulfilled(bytes32 indexed thawRequestId, uint256 tokens, uint256 shares, uint64 thawingUntil); + event ThawRequestFulfilled( + bytes32 indexed thawRequestId, + uint256 tokens, + uint256 shares, + uint64 thawingUntil, + bool valid + ); /** * @notice Emitted when a series of thaw requests are fulfilled. @@ -742,6 +749,8 @@ interface IHorizonStakingMain { * Tokens can be automatically re-delegated to another provision by setting `newServiceProvider`. * @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw * requests in the event that fulfilling all of them results in a gas limit error. + * @dev If the delegation pool was completely slashed before withdrawing, calling this function will fulfill + * the thaw requests with an amount equal to zero. * * Requirements: * - Must have previously initiated a thaw request using {undelegate}. diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index 42b5588ef..0dfc6c774 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -32,6 +32,8 @@ interface IHorizonStakingTypes { uint32 maxVerifierCutPending; // Pending value for `thawingPeriod`. Verifier needs to accept it before it becomes active. uint64 thawingPeriodPending; + // Value of the current thawing nonce. Thaw requests with older nonces are invalid. + uint256 thawingNonce; } /** @@ -75,6 +77,8 @@ interface IHorizonStakingTypes { uint256 tokensThawing; // Shares representing the thawing tokens uint256 sharesThawing; + // Value of the current thawing nonce. Thaw requests with older nonces are invalid. + uint256 thawingNonce; } /** @@ -101,6 +105,8 @@ interface IHorizonStakingTypes { uint256 tokensThawing; // Shares representing the thawing tokens uint256 sharesThawing; + // Value of the current thawing nonce. Thaw requests with older nonces are invalid. + uint256 thawingNonce; } /** @@ -137,5 +143,7 @@ interface IHorizonStakingTypes { uint64 thawingUntil; // Id of the next thaw request in the linked list bytes32 next; + // Used to invalidate unfulfilled thaw requests + uint256 thawingNonce; } } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 8f3fb524a..476437ffb 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -411,6 +411,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { (FIXED_POINT_PRECISION); prov.tokens = prov.tokens - providerTokensSlashed; + // If the slashing leaves the thawing shares with no thawing tokens, cancel pending thawings by: + // - deleting all thawing shares + // - incrementing the nonce to invalidate pending thaw requests + if (prov.sharesThawing != 0 && prov.tokensThawing == 0) { + prov.sharesThawing = 0; + prov.thawingNonce++; + } + // Service provider accounting _serviceProviders[serviceProvider].tokensProvisioned = _serviceProviders[serviceProvider].tokensProvisioned - @@ -438,6 +446,16 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { (pool.tokensThawing * (FIXED_POINT_PRECISION - delegationFractionSlashed)) / FIXED_POINT_PRECISION; + // If the slashing leaves the thawing shares with no thawing tokens, cancel pending thawings by: + // - deleting all thawing shares + // - incrementing the nonce to invalidate pending thaw requests + // Note that thawing shares are completely lost, delegators won't get back the corresponding + // delegation pool shares. + if (pool.sharesThawing != 0 && pool.tokensThawing == 0) { + pool.sharesThawing = 0; + pool.thawingNonce++; + } + emit DelegationSlashed(serviceProvider, verifier, tokensToSlash); } else { emit DelegationSlashingSkipped(serviceProvider, verifier, tokensToSlash); @@ -644,7 +662,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { thawingPeriod: _thawingPeriod, createdAt: uint64(block.timestamp), maxVerifierCutPending: _maxVerifierCut, - thawingPeriodPending: _thawingPeriod + thawingPeriodPending: _thawingPeriod, + thawingNonce: 0 }); ServiceProviderInternal storage sp = _serviceProviders[_serviceProvider]; @@ -672,6 +691,9 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { /** * @notice See {IHorizonStakingMain-thaw}. + * @dev We use a thawing pool to keep track of tokens thawing for multiple thaw requests. + * If due to slashing the thawing pool loses all of its tokens, the pool is reset and all pending thaw + * requests are invalidated. */ function _thaw(address _serviceProvider, address _verifier, uint256 _tokens) private returns (bytes32) { require(_tokens != 0, HorizonStakingInvalidZeroTokens()); @@ -679,18 +701,24 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { require(tokensAvailable >= _tokens, HorizonStakingInsufficientTokens(tokensAvailable, _tokens)); Provision storage prov = _provisions[_serviceProvider][_verifier]; - uint256 thawingShares = prov.sharesThawing == 0 ? _tokens : (prov.sharesThawing * _tokens) / prov.tokensThawing; + + // Calculate shares to issue + // Thawing pool is reset/initialized when the pool is empty: prov.tokensThawing == 0 + uint256 thawingShares = prov.tokensThawing == 0 + ? _tokens + : ((prov.sharesThawing * _tokens) / prov.tokensThawing); uint64 thawingUntil = uint64(block.timestamp + uint256(prov.thawingPeriod)); - prov.tokensThawing = prov.tokensThawing + _tokens; prov.sharesThawing = prov.sharesThawing + thawingShares; + prov.tokensThawing = prov.tokensThawing + _tokens; bytes32 thawRequestId = _createThawRequest( _serviceProvider, _verifier, _serviceProvider, thawingShares, - thawingUntil + thawingUntil, + prov.thawingNonce ); emit ProvisionThawed(_serviceProvider, _verifier, _tokens); return thawRequestId; @@ -715,7 +743,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _serviceProvider, tokensThawing, sharesThawing, - _nThawRequests + _nThawRequests, + prov.thawingNonce ); prov.tokens = prov.tokens - tokensThawed_; @@ -741,15 +770,19 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); DelegationInternal storage delegation = pool.delegators[msg.sender]; + // An invalid delegation pool has shares but no tokens require( - pool.tokens != 0 || (pool.shares == 0 && pool.sharesThawing == 0), + pool.tokens != 0 || pool.shares == 0, HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier) ); // Calculate shares to issue - uint256 shares = (pool.tokens == 0 || pool.tokens == pool.tokensThawing) - ? _tokens - : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); + // Delegation pool is reset/initialized in any of the following cases: + // - pool.tokens == 0 and pool.shares == 0, pool is completely empty. Note that we don't test shares == 0 because + // the invalid delegation pool check already ensures shares are 0 if tokens are 0 + // - pool.tokens == pool.tokensThawing, the entire pool is thawing + bool initializePool = pool.tokens == 0 || pool.tokens == pool.tokensThawing; + uint256 shares = initializePool ? _tokens : ((_tokens * pool.shares) / (pool.tokens - pool.tokensThawing)); require(shares != 0 && shares >= _minSharesOut, HorizonStakingSlippageProtection(shares, _minSharesOut)); pool.tokens = pool.tokens + _tokens; @@ -764,6 +797,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice See {IHorizonStakingMain-undelegate}. * @dev To allow delegation to be slashable even while thawing without breaking accounting * the delegation pool shares are burned and replaced with thawing pool shares. + * @dev Note that due to slashing the delegation pool can enter an invalid state if all it's tokens are slashed. + * An invalid pool can only be recovered by adding back tokens into the pool with {IHorizonStakingMain-addToDelegationPool}. + * Any time the delegation pool is invalidated, the thawing pool is also reset and any pending undelegate requests get + * invalidated. + * Note that delegation that is caught thawing when the pool is invalidated will be completely lost! However delegation shares + * that were not thawing will be preserved. */ function _undelegate( address _serviceProvider, @@ -775,15 +814,21 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); DelegationInternal storage delegation = pool.delegators[msg.sender]; require(delegation.shares >= _shares, HorizonStakingInsufficientShares(delegation.shares, _shares)); + + // An invalid delegation pool has shares but no tokens (previous require check ensures shares > 0) require(pool.tokens != 0, HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier)); + // Calculate thawing shares to issue - convert delegation pool shares to thawing pool shares + // delegation pool shares -> delegation pool tokens -> thawing pool shares + // Thawing pool is reset/initialized when the pool is empty: prov.tokensThawing == 0 uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares; uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing); uint64 thawingUntil = uint64(block.timestamp + uint256(_provisions[_serviceProvider][_verifier].thawingPeriod)); - pool.shares = pool.shares - _shares; + pool.tokensThawing = pool.tokensThawing + tokens; pool.sharesThawing = pool.sharesThawing + thawingShares; + pool.shares = pool.shares - _shares; delegation.shares = delegation.shares - _shares; bytes32 thawRequestId = _createThawRequest( @@ -791,7 +836,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _verifier, beneficiary, thawingShares, - thawingUntil + thawingUntil, + pool.thawingNonce ); emit TokensUndelegated(_serviceProvider, _verifier, msg.sender, tokens); @@ -809,7 +855,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { uint256 _nThawRequests ) private { DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); - require(pool.tokens != 0, HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier)); + + // An invalid delegation pool has shares but no tokens + require( + pool.tokens != 0 || pool.shares == 0, + HorizonStakingInvalidDelegationPoolState(_serviceProvider, _verifier) + ); uint256 tokensThawed = 0; uint256 sharesThawing = pool.sharesThawing; @@ -820,9 +871,12 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { msg.sender, tokensThawing, sharesThawing, - _nThawRequests + _nThawRequests, + pool.thawingNonce ); + // The next subtraction should never revert becase: pool.tokens >= pool.tokensThawing and pool.tokensThawing >= tokensThawed + // In the event the pool gets completely slashed tokensThawed will fulfil to 0. pool.tokens = pool.tokens - tokensThawed; pool.sharesThawing = sharesThawing; pool.tokensThawing = tokensThawing; @@ -849,6 +903,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param _owner The address of the owner of the thaw request * @param _shares The number of shares to thaw * @param _thawingUntil The timestamp until which the shares are thawing + * @param _thawingNonce Owner's validity nonce for the thaw request * @return The ID of the thaw request */ function _createThawRequest( @@ -856,13 +911,19 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address _verifier, address _owner, uint256 _shares, - uint64 _thawingUntil + uint64 _thawingUntil, + uint256 _thawingNonce ) private returns (bytes32) { LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; require(thawRequestList.count < MAX_THAW_REQUESTS, HorizonStakingTooManyThawRequests()); bytes32 thawRequestId = keccak256(abi.encodePacked(_serviceProvider, _verifier, _owner, thawRequestList.nonce)); - _thawRequests[thawRequestId] = ThawRequest({ shares: _shares, thawingUntil: _thawingUntil, next: bytes32(0) }); + _thawRequests[thawRequestId] = ThawRequest({ + shares: _shares, + thawingUntil: _thawingUntil, + next: bytes32(0), + thawingNonce: _thawingNonce + }); if (thawRequestList.count != 0) _thawRequests[thawRequestList.tail].next = thawRequestId; thawRequestList.addTail(thawRequestId); @@ -880,6 +941,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @param _tokensThawing The current amount of tokens already thawing * @param _sharesThawing The current amount of shares already thawing * @param _nThawRequests The number of thaw requests to fulfill. If set to 0, all thaw requests are fulfilled. + * @param _thawingNonce The current valid thawing nonce. Any thaw request with a different nonce is invalid and should be ignored. * @return The amount of thawed tokens * @return The amount of tokens still thawing * @return The amount of shares still thawing @@ -890,7 +952,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address _owner, uint256 _tokensThawing, uint256 _sharesThawing, - uint256 _nThawRequests + uint256 _nThawRequests, + uint256 _thawingNonce ) private returns (uint256, uint256, uint256) { LinkedList.List storage thawRequestList = _thawRequestLists[_serviceProvider][_verifier][_owner]; require(thawRequestList.count > 0, HorizonStakingNothingThawing()); @@ -900,7 +963,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { _getNextThawRequest, _fulfillThawRequest, _deleteThawRequest, - abi.encode(tokensThawed, _tokensThawing, _sharesThawing), + abi.encode(tokensThawed, _tokensThawing, _sharesThawing, _thawingNonce), _nThawRequests ); @@ -929,20 +992,30 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { } // decode - (uint256 tokensThawed, uint256 tokensThawing, uint256 sharesThawing) = abi.decode( + (uint256 tokensThawed, uint256 tokensThawing, uint256 sharesThawing, uint256 thawingNonce) = abi.decode( _acc, - (uint256, uint256, uint256) + (uint256, uint256, uint256, uint256) ); - // process - uint256 tokens = (thawRequest.shares * tokensThawing) / sharesThawing; - tokensThawing = tokensThawing - tokens; - sharesThawing = sharesThawing - thawRequest.shares; - tokensThawed = tokensThawed + tokens; - emit ThawRequestFulfilled(_thawRequestId, tokens, thawRequest.shares, thawRequest.thawingUntil); + // process - only fulfill thaw requests for the current valid nonce + uint256 tokens = 0; + bool validThawRequest = thawRequest.thawingNonce == thawingNonce; + if (validThawRequest) { + tokens = (thawRequest.shares * tokensThawing) / sharesThawing; + tokensThawing = tokensThawing - tokens; + sharesThawing = sharesThawing - thawRequest.shares; + tokensThawed = tokensThawed + tokens; + } + emit ThawRequestFulfilled( + _thawRequestId, + tokens, + thawRequest.shares, + thawRequest.thawingUntil, + validThawRequest + ); // encode - _acc = abi.encode(tokensThawed, tokensThawing, sharesThawing); + _acc = abi.encode(tokensThawed, tokensThawing, sharesThawing, thawingNonce); return (false, _acc); } diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index d9fb613c3..54e55e1cc 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -96,6 +96,7 @@ abstract contract HorizonStakingBase is pool.shares = poolInternal.shares; pool.tokensThawing = poolInternal.tokensThawing; pool.sharesThawing = poolInternal.sharesThawing; + pool.thawingNonce = poolInternal.thawingNonce; return pool; } diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index b13128c72..d6d88283f 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -351,6 +351,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.createdAt, uint64(block.timestamp)); assertEq(afterProvision.maxVerifierCutPending, maxVerifierCut); assertEq(afterProvision.thawingPeriodPending, thawingPeriod); + assertEq(afterProvision.thawingNonce, 0); assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked); assertEq(afterServiceProvider.tokensProvisioned, tokens + beforeServiceProvider.tokensProvisioned); assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); @@ -384,6 +385,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.createdAt, beforeProvision.createdAt); assertEq(afterProvision.maxVerifierCutPending, beforeProvision.maxVerifierCutPending); assertEq(afterProvision.thawingPeriodPending, beforeProvision.thawingPeriodPending); + assertEq(afterProvision.thawingNonce, beforeProvision.thawingNonce); assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked); assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned + tokens); assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); @@ -406,7 +408,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { bytes32 expectedThawRequestId = keccak256( abi.encodePacked(users.indexer, verifier, users.indexer, beforeThawRequestList.nonce) ); - uint256 thawingShares = beforeProvision.sharesThawing == 0 + uint256 thawingShares = beforeProvision.tokensThawing == 0 ? tokens : (beforeProvision.sharesThawing * tokens) / beforeProvision.tokensThawing; @@ -437,12 +439,16 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { // assert assertEq(afterProvision.tokens, beforeProvision.tokens); assertEq(afterProvision.tokensThawing, beforeProvision.tokensThawing + tokens); - assertEq(afterProvision.sharesThawing, beforeProvision.sharesThawing + thawingShares); + assertEq( + afterProvision.sharesThawing, + beforeProvision.tokensThawing == 0 ? thawingShares : beforeProvision.sharesThawing + thawingShares + ); assertEq(afterProvision.maxVerifierCut, beforeProvision.maxVerifierCut); assertEq(afterProvision.thawingPeriod, beforeProvision.thawingPeriod); assertEq(afterProvision.createdAt, beforeProvision.createdAt); assertEq(afterProvision.maxVerifierCutPending, beforeProvision.maxVerifierCutPending); assertEq(afterProvision.thawingPeriodPending, beforeProvision.thawingPeriodPending); + assertEq(afterProvision.thawingNonce, beforeProvision.thawingNonce); assertEq(thawRequestId, expectedThawRequestId); assertEq(afterThawRequest.shares, thawingShares); assertEq(afterThawRequest.thawingUntil, block.timestamp + beforeProvision.thawingPeriod); @@ -471,7 +477,13 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { serviceProvider ); - CalcValues_ThawRequestData memory calcValues = calcThawRequestData(serviceProvider, verifier, serviceProvider, nThawRequests, false); + CalcValues_ThawRequestData memory calcValues = calcThawRequestData( + serviceProvider, + verifier, + serviceProvider, + nThawRequests, + false + ); // deprovision for (uint i = 0; i < calcValues.thawRequestsFulfilledList.length; i++) { @@ -481,7 +493,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { calcValues.thawRequestsFulfilledListIds[i], calcValues.thawRequestsFulfilledListTokens[i], thawRequest.shares, - thawRequest.thawingUntil + thawRequest.thawingUntil, + beforeProvision.thawingNonce == thawRequest.thawingNonce ); } vm.expectEmit(address(staking)); @@ -514,8 +527,12 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.createdAt, beforeProvision.createdAt); assertEq(afterProvision.maxVerifierCutPending, beforeProvision.maxVerifierCutPending); assertEq(afterProvision.thawingPeriodPending, beforeProvision.thawingPeriodPending); + assertEq(afterProvision.thawingNonce, beforeProvision.thawingNonce); assertEq(afterServiceProvider.tokensStaked, beforeServiceProvider.tokensStaked); - assertEq(afterServiceProvider.tokensProvisioned, beforeServiceProvider.tokensProvisioned - calcValues.tokensThawed); + assertEq( + afterServiceProvider.tokensProvisioned, + beforeServiceProvider.tokensProvisioned - calcValues.tokensThawed + ); assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeServiceProvider.__DEPRECATED_tokensAllocated); assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeServiceProvider.__DEPRECATED_tokensLocked); assertEq( @@ -554,6 +571,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { ServiceProviderInternal serviceProvider; LinkedList.List thawRequestList; } + function _reprovision( address serviceProvider, address verifier, @@ -569,7 +587,13 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { }); // calc - CalcValues_ThawRequestData memory calcValues = calcThawRequestData(serviceProvider, verifier, serviceProvider, nThawRequests, false); + CalcValues_ThawRequestData memory calcValues = calcThawRequestData( + serviceProvider, + verifier, + serviceProvider, + nThawRequests, + false + ); // reprovision for (uint i = 0; i < calcValues.thawRequestsFulfilledList.length; i++) { @@ -579,7 +603,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { calcValues.thawRequestsFulfilledListIds[i], calcValues.thawRequestsFulfilledListTokens[i], thawRequest.shares, - thawRequest.thawingUntil + thawRequest.thawingUntil, + beforeValues.provision.thawingNonce == thawRequest.thawingNonce ); } vm.expectEmit(address(staking)); @@ -615,6 +640,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.createdAt, beforeValues.provision.createdAt); assertEq(afterProvision.maxVerifierCutPending, beforeValues.provision.maxVerifierCutPending); assertEq(afterProvision.thawingPeriodPending, beforeValues.provision.thawingPeriodPending); + assertEq(afterProvision.thawingNonce, beforeValues.provision.thawingNonce); // assert: provision new verifier assertEq(afterProvisionNewVerifier.tokens, beforeValues.provisionNewVerifier.tokens + calcValues.tokensThawed); @@ -623,8 +649,15 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvisionNewVerifier.maxVerifierCut, beforeValues.provisionNewVerifier.maxVerifierCut); assertEq(afterProvisionNewVerifier.thawingPeriod, beforeValues.provisionNewVerifier.thawingPeriod); assertEq(afterProvisionNewVerifier.createdAt, beforeValues.provisionNewVerifier.createdAt); - assertEq(afterProvisionNewVerifier.maxVerifierCutPending, beforeValues.provisionNewVerifier.maxVerifierCutPending); - assertEq(afterProvisionNewVerifier.thawingPeriodPending, beforeValues.provisionNewVerifier.thawingPeriodPending); + assertEq( + afterProvisionNewVerifier.maxVerifierCutPending, + beforeValues.provisionNewVerifier.maxVerifierCutPending + ); + assertEq( + afterProvisionNewVerifier.thawingPeriodPending, + beforeValues.provisionNewVerifier.thawingPeriodPending + ); + assertEq(afterProvisionNewVerifier.thawingNonce, beforeValues.provisionNewVerifier.thawingNonce); // assert: service provider assertEq(afterServiceProvider.tokensStaked, beforeValues.serviceProvider.tokensStaked); @@ -632,8 +665,14 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { afterServiceProvider.tokensProvisioned, beforeValues.serviceProvider.tokensProvisioned + calcValues.tokensThawed - calcValues.tokensThawed ); - assertEq(afterServiceProvider.__DEPRECATED_tokensAllocated, beforeValues.serviceProvider.__DEPRECATED_tokensAllocated); - assertEq(afterServiceProvider.__DEPRECATED_tokensLocked, beforeValues.serviceProvider.__DEPRECATED_tokensLocked); + assertEq( + afterServiceProvider.__DEPRECATED_tokensAllocated, + beforeValues.serviceProvider.__DEPRECATED_tokensAllocated + ); + assertEq( + afterServiceProvider.__DEPRECATED_tokensLocked, + beforeValues.serviceProvider.__DEPRECATED_tokensLocked + ); assertEq( afterServiceProvider.__DEPRECATED_tokensLockedUntil, beforeValues.serviceProvider.__DEPRECATED_tokensLockedUntil @@ -662,7 +701,10 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { ? bytes32(0) : beforeValues.thawRequestList.tail ); - assertEq(afterThawRequestList.count, beforeValues.thawRequestList.count - calcValues.thawRequestsFulfilledList.length); + assertEq( + afterThawRequestList.count, + beforeValues.thawRequestList.count - calcValues.thawRequestsFulfilledList.length + ); assertEq(afterThawRequestList.nonce, beforeValues.thawRequestList.nonce); } @@ -699,6 +741,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.createdAt, beforeProvision.createdAt); assertEq(afterProvision.maxVerifierCutPending, maxVerifierCut); assertEq(afterProvision.thawingPeriodPending, thawingPeriod); + assertEq(afterProvision.thawingNonce, beforeProvision.thawingNonce); } function _acceptProvisionParameters(address serviceProvider) internal { @@ -734,6 +777,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterProvision.thawingPeriod, beforeProvision.thawingPeriodPending); assertEq(afterProvision.thawingPeriod, afterProvision.thawingPeriodPending); assertEq(afterProvision.createdAt, beforeProvision.createdAt); + assertEq(afterProvision.thawingNonce, beforeProvision.thawingNonce); } function _setOperator(address verifier, address operator, bool allow) internal { @@ -842,6 +886,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(beforePool.shares + calcShares, afterPool.shares); assertEq(beforePool.tokensThawing, afterPool.tokensThawing); assertEq(beforePool.sharesThawing, afterPool.sharesThawing); + assertEq(beforePool.thawingNonce, afterPool.thawingNonce); assertEq(beforeDelegation.shares + calcShares, afterDelegation.shares); assertEq(beforeDelegation.__DEPRECATED_tokensLocked, afterDelegation.__DEPRECATED_tokensLocked); assertEq(beforeDelegation.__DEPRECATED_tokensLockedUntil, afterDelegation.__DEPRECATED_tokensLockedUntil); @@ -890,7 +935,9 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { // calc CalcValues_Undelegate memory calcValues; - calcValues.tokens = ((beforeValues.pool.tokens - beforeValues.pool.tokensThawing) * shares) / beforeValues.pool.shares; + calcValues.tokens = + ((beforeValues.pool.tokens - beforeValues.pool.tokensThawing) * shares) / + beforeValues.pool.shares; calcValues.thawingShares = beforeValues.pool.tokensThawing == 0 ? calcValues.tokens : (beforeValues.pool.sharesThawing * calcValues.tokens) / beforeValues.pool.tokensThawing; @@ -939,7 +986,13 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(beforeValues.pool.shares, afterPool.shares + shares); assertEq(beforeValues.pool.tokens, afterPool.tokens); assertEq(beforeValues.pool.tokensThawing + calcValues.tokens, afterPool.tokensThawing); - assertEq(beforeValues.pool.sharesThawing + calcValues.thawingShares, afterPool.sharesThawing); + assertEq( + beforeValues.pool.tokensThawing == 0 + ? calcValues.thawingShares + : beforeValues.pool.sharesThawing + calcValues.thawingShares, + afterPool.sharesThawing + ); + assertEq(beforeValues.pool.thawingNonce, afterPool.thawingNonce); assertEq(beforeValues.delegation.shares - shares, afterDelegation.shares); assertEq(afterThawRequest.shares, calcValues.thawingShares); assertEq(afterThawRequest.thawingUntil, calcValues.thawingUntil); @@ -987,6 +1040,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { uint256 senderBalance; uint256 stakingBalance; } + function __withdrawDelegated( address _serviceProvider, address _verifier, @@ -1024,7 +1078,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { calcValues.thawRequestsFulfilledListIds[i], calcValues.thawRequestsFulfilledListTokens[i], thawRequest.shares, - thawRequest.thawingUntil + thawRequest.thawingUntil, + beforeValues.pool.thawingNonce == thawRequest.thawingNonce ); } vm.expectEmit(address(staking)); @@ -1038,13 +1093,23 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { if (calcValues.tokensThawed != 0) { vm.expectEmit(); if (reDelegate) { - emit IHorizonStakingMain.TokensDelegated(_newServiceProvider, _verifier, msgSender, calcValues.tokensThawed); + emit IHorizonStakingMain.TokensDelegated( + _newServiceProvider, + _verifier, + msgSender, + calcValues.tokensThawed + ); } else { emit Transfer(address(staking), msgSender, calcValues.tokensThawed); } } vm.expectEmit(); - emit IHorizonStakingMain.DelegatedTokensWithdrawn(_serviceProvider, _verifier, msgSender, calcValues.tokensThawed); + emit IHorizonStakingMain.DelegatedTokensWithdrawn( + _serviceProvider, + _verifier, + msgSender, + calcValues.tokensThawed + ); staking.withdrawDelegated( _serviceProvider, _verifier, @@ -1067,6 +1132,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterValues.pool.shares, beforeValues.pool.shares); assertEq(afterValues.pool.tokensThawing, calcValues.tokensThawing); assertEq(afterValues.pool.sharesThawing, calcValues.sharesThawing); + assertEq(afterValues.pool.thawingNonce, beforeValues.pool.thawingNonce); for (uint i = 0; i < calcValues.thawRequestsFulfilledListIds.length; i++) { ThawRequest memory thawRequest = staking.getThawRequest(calcValues.thawRequestsFulfilledListIds[i]); @@ -1090,7 +1156,10 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { ? bytes32(0) : beforeValues.thawRequestList.tail ); - assertEq(afterValues.thawRequestList.count, beforeValues.thawRequestList.count - calcValues.thawRequestsFulfilledList.length); + assertEq( + afterValues.thawRequestList.count, + beforeValues.thawRequestList.count - calcValues.thawRequestsFulfilledList.length + ); assertEq(afterValues.thawRequestList.nonce, beforeValues.thawRequestList.nonce); if (reDelegate) { @@ -1106,7 +1175,10 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterValues.newPool.tokensThawing, beforeValues.newPool.tokensThawing); assertEq(afterValues.newPool.sharesThawing, beforeValues.newPool.sharesThawing); assertEq(afterValues.newDelegation.shares, beforeValues.newDelegation.shares + calcShares); - assertEq(afterValues.newDelegation.__DEPRECATED_tokensLocked, beforeValues.newDelegation.__DEPRECATED_tokensLocked); + assertEq( + afterValues.newDelegation.__DEPRECATED_tokensLocked, + beforeValues.newDelegation.__DEPRECATED_tokensLocked + ); assertEq( afterValues.newDelegation.__DEPRECATED_tokensLockedUntil, beforeValues.newDelegation.__DEPRECATED_tokensLockedUntil @@ -1160,6 +1232,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(beforePool.shares, afterPool.shares); assertEq(beforePool.tokensThawing, afterPool.tokensThawing); assertEq(beforePool.sharesThawing, afterPool.sharesThawing); + assertEq(beforePool.thawingNonce, afterPool.thawingNonce); } function _setDelegationFeeCut( @@ -1322,19 +1395,25 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { // assert assertEq(afterProvision.tokens + calcValues.providerTokensSlashed, before.provision.tokens); assertEq(afterProvision.tokensThawing, provisionThawingTokens); - assertEq(afterProvision.sharesThawing, before.provision.sharesThawing); + assertEq( + afterProvision.sharesThawing, + afterProvision.tokensThawing == 0 ? 0 : before.provision.sharesThawing + ); assertEq(afterProvision.maxVerifierCut, before.provision.maxVerifierCut); assertEq(afterProvision.maxVerifierCutPending, before.provision.maxVerifierCutPending); assertEq(afterProvision.thawingPeriod, before.provision.thawingPeriod); assertEq(afterProvision.thawingPeriodPending, before.provision.thawingPeriodPending); - + assertEq( + afterProvision.thawingNonce, + (before.provision.sharesThawing != 0 && afterProvision.sharesThawing == 0) ? before.provision.thawingNonce + 1 : before.provision.thawingNonce); if (isDelegationSlashingEnabled) { uint256 poolThawingTokens = (before.pool.tokensThawing * (1e18 - ((calcValues.delegationTokensSlashed * 1e18) / before.pool.tokens))) / (1e18); assertEq(afterPool.tokens + calcValues.delegationTokensSlashed, before.pool.tokens); assertEq(afterPool.shares, before.pool.shares); assertEq(afterPool.tokensThawing, poolThawingTokens); - assertEq(afterPool.sharesThawing, before.pool.sharesThawing); + assertEq(afterPool.sharesThawing, afterPool.tokensThawing == 0 ? 0 : before.pool.sharesThawing); + assertEq(afterPool.thawingNonce, (before.pool.sharesThawing != 0 && afterPool.sharesThawing == 0) ? before.pool.thawingNonce + 1 : before.pool.thawingNonce); } assertEq(before.stakingBalance - tokensSlashed, afterStakingBalance); @@ -1652,6 +1731,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { assertEq(afterValues.pool.shares, beforeValues.pool.shares); assertEq(afterValues.pool.tokensThawing, beforeValues.pool.tokensThawing); assertEq(afterValues.pool.sharesThawing, beforeValues.pool.sharesThawing); + assertEq(afterValues.pool.thawingNonce, beforeValues.pool.thawingNonce); assertEq(afterValues.serviceProvider.tokensProvisioned, beforeValues.serviceProvider.tokensProvisioned); if (rewardsDestination != address(0)) { @@ -1763,6 +1843,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { uint256 tokensThawing; // Shares representing the thawing tokens uint256 sharesThawing; + // Thawing nonce + uint256 thawingNonce; } function _getStorage_DelegationPoolInternal( @@ -1789,7 +1871,8 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { shares: uint256(vm.load(address(staking), bytes32(baseSlot + 3))), _gap_delegators_mapping: uint256(vm.load(address(staking), bytes32(baseSlot + 4))), tokensThawing: uint256(vm.load(address(staking), bytes32(baseSlot + 5))), - sharesThawing: uint256(vm.load(address(staking), bytes32(baseSlot + 6))) + sharesThawing: uint256(vm.load(address(staking), bytes32(baseSlot + 6))), + thawingNonce: uint256(vm.load(address(staking), bytes32(baseSlot + 7))) }); return delegationPoolInternal; @@ -2120,14 +2203,17 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { bytes32 thawRequestId = thawRequestList.head; while (thawRequestId != bytes32(0) && (iterations == 0 || thawRequestsFulfilled < iterations)) { ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + bool isThawRequestValid = thawRequest.thawingNonce == (delegation ? pool.thawingNonce : prov.thawingNonce); if (thawRequest.thawingUntil <= block.timestamp) { thawRequestsFulfilled++; - uint256 tokens = delegation - ? (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing - : (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; - tokensThawed += tokens; - tokensThawing -= tokens; - sharesThawing -= thawRequest.shares; + if (isThawRequestValid) { + uint256 tokens = delegation + ? (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing + : (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; + tokensThawed += tokens; + tokensThawing -= tokens; + sharesThawing -= thawRequest.shares; + } } else { break; } @@ -2142,11 +2228,14 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { thawRequestId = thawRequestList.head; while (thawRequestId != bytes32(0) && (iterations == 0 || i < iterations)) { ThawRequest memory thawRequest = staking.getThawRequest(thawRequestId); + bool isThawRequestValid = thawRequest.thawingNonce == (delegation ? pool.thawingNonce : prov.thawingNonce); + if (thawRequest.thawingUntil <= block.timestamp) { - uint256 tokens = delegation - ? (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing - : (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; - thawRequestsFulfilledListTokens[i] = tokens; + if (isThawRequestValid) { + thawRequestsFulfilledListTokens[i] = delegation + ? (thawRequest.shares * pool.tokensThawing) / pool.sharesThawing + : (thawRequest.shares * prov.tokensThawing) / prov.sharesThawing; + } thawRequestsFulfilledListIds[i] = thawRequestId; thawRequestsFulfilledList[i] = staking.getThawRequest(thawRequestId); thawRequestId = thawRequestsFulfilledList[i].next; diff --git a/packages/horizon/test/staking/delegation/addToPool.t.sol b/packages/horizon/test/staking/delegation/addToPool.t.sol index de2647dfc..ff5b957ca 100644 --- a/packages/horizon/test/staking/delegation/addToPool.t.sol +++ b/packages/horizon/test/staking/delegation/addToPool.t.sol @@ -76,7 +76,7 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 1); } - function test_Deletaion_AddToPool_RevertWhen_NoProvision() public { + function test_Delegation_AddToPool_RevertWhen_NoProvision() public { vm.startPrank(subgraphDataServiceAddress); bytes memory expectedError = abi.encodeWithSelector( IHorizonStakingMain.HorizonStakingInvalidProvision.selector, @@ -87,5 +87,62 @@ contract HorizonStakingDelegationAddToPoolTest is HorizonStakingTest { staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 1); } - // TODO: test recovering an invalid delegation pool + function test_Delegation_AddToPool_WhenInvalidPool( + uint256 tokens, + uint256 delegationTokens, + uint256 recoverAmount + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { + recoverAmount = bound(recoverAmount, 1, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + + // create delegation pool + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // slash entire provision + pool + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + + // recover pool by adding tokens + resetPrank(users.indexer); + token.approve(address(staking), recoverAmount); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, recoverAmount); + } + + + function test_Delegation_AddToPool_WhenInvalidPool_RevertWhen_PoolHasNoShares( + uint256 tokens, + uint256 delegationTokens, + uint256 recoverAmount + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { + recoverAmount = bound(recoverAmount, 1, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + + // create delegation pool + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // undelegate shares so we have thawing shares/tokens + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); + resetPrank(users.delegator); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); + + // slash entire provision + pool + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + + // addTokens + bytes memory expectedError = abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPool.selector, + users.indexer, + subgraphDataServiceAddress + ); + vm.expectRevert(expectedError); + staking.addToDelegationPool(users.indexer, subgraphDataServiceAddress, 1); + } } \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/delegate.t.sol b/packages/horizon/test/staking/delegation/delegate.t.sol index 5deb9b495..ab58e4bde 100644 --- a/packages/horizon/test/staking/delegation/delegate.t.sol +++ b/packages/horizon/test/staking/delegation/delegate.t.sol @@ -73,12 +73,15 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + // slash entire provision + pool resetPrank(subgraphDataServiceAddress); _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + // attempt to delegate to a pool on invalid state, should revert resetPrank(users.delegator); token.approve(address(staking), delegationTokens); vm.expectRevert(abi.encodeWithSelector( @@ -93,15 +96,20 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { uint256 tokens, uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { - delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 2, MAX_STAKING_TOKENS); + resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // undelegate some shares but not all DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); - _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares / 2); + // slash entire provision + pool resetPrank(subgraphDataServiceAddress); _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); - + + // attempt to delegate to a pool on invalid state, should revert resetPrank(users.delegator); token.approve(address(staking), delegationTokens); vm.expectRevert(abi.encodeWithSelector( @@ -111,4 +119,31 @@ contract HorizonStakingDelegateTest is HorizonStakingTest { )); staking.delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); } + + function testDelegate_AfterRecoveringPool( + uint256 tokens, + uint256 delegationTokens, + uint256 recoverAmount + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { + recoverAmount = bound(recoverAmount, 1, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + + // create delegation pool + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // slash entire provision + pool + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + + // recover pool by adding tokens + resetPrank(users.indexer); + token.approve(address(staking), recoverAmount); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, recoverAmount); + + // delegate to pool - should be allowed now + vm.assume(delegationTokens >= recoverAmount); // to avoid getting issued 0 shares + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + } } diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index c5d61b6e5..4cad2e0c3 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -17,7 +17,12 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 delegationAmount ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); } @@ -31,7 +36,12 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationAmount, 0); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); uint256 undelegateAmount = delegation.shares / undelegateSteps; for (uint i = 0; i < undelegateSteps; i++) { @@ -83,7 +93,12 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 overDelegationShares ) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) { resetPrank(users.delegator); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); overDelegationShares = bound(overDelegationShares, delegation.shares + 1, MAX_STAKING_TOKENS + 1); bytes memory expectedError = abi.encodeWithSignature( @@ -103,7 +118,12 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { resetPrank(users.delegator); _delegate(users.indexer, delegationAmount); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, true); + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + true + ); _undelegate(users.indexer, delegation.shares); } @@ -112,22 +132,98 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest { uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing() { delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + // slash all of the provision + delegation resetPrank(subgraphDataServiceAddress); _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); - + + // attempt to undelegate - should revert resetPrank(users.delegator); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); - vm.expectRevert(abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, + DelegationInternal memory delegation = _getStorage_Delegation( users.indexer, - subgraphDataServiceAddress - )); + subgraphDataServiceAddress, + users.delegator, + false + ); + vm.expectRevert( + abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, + users.indexer, + subgraphDataServiceAddress + ) + ); staking.undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); } + function testUndelegate_AfterRecoveringPool( + uint256 tokens, + uint256 delegationTokens + ) public useIndexer useProvision(tokens, 0, 0) useDelegationSlashing { + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + + // delegate + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // slash all of the provision + delegation + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + + // recover the delegation pool + resetPrank(users.indexer); + token.approve(address(staking), delegationTokens); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationTokens); + + // undelegate -- should now work + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); + resetPrank(users.delegator); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); + } + + function testUndelegate_ThawingShares_AfterRecoveringPool() + public + useIndexer + useProvision(MAX_STAKING_TOKENS, 0, 0) + useDelegationSlashing + { + uint256 delegationTokens = MAX_STAKING_TOKENS / 10; + + // delegate + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // undelegate half shares so we have some thawing shares/tokens + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); + resetPrank(users.delegator); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares / 2); + + // slash all of the provision + delegation + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, MAX_STAKING_TOKENS + delegationTokens, 0); + + // recover the delegation pool + resetPrank(users.indexer); + token.approve(address(staking), delegationTokens); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationTokens); + + // undelegate the rest + resetPrank(users.delegator); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares - delegation.shares / 2); + } + function testUndelegate_RevertIf_BeneficiaryIsZero( uint256 amount, uint256 delegationAmount diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index b7644c62a..c66126e1c 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -9,7 +9,6 @@ import { LinkedList } from "../../../contracts/libraries/LinkedList.sol"; import { HorizonStakingTest } from "../HorizonStaking.t.sol"; contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { - /* * MODIFIERS */ @@ -17,7 +16,12 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { modifier useUndelegate(uint256 shares) { vm.stopPrank(); vm.startPrank(users.delegator); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); shares = bound(shares, 1, delegation.shares); _undelegate(users.indexer, subgraphDataServiceAddress, shares); @@ -27,8 +31,8 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { /* * HELPERS */ - function _setupNewIndexer(uint256 tokens) private returns(address) { - (, address msgSender,) = vm.readCallers(); + function _setupNewIndexer(uint256 tokens) private returns (address) { + (, address msgSender, ) = vm.readCallers(); address newIndexer = createUser("newIndexer"); vm.startPrank(newIndexer); @@ -52,7 +56,11 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useDelegation(delegationAmount) useUndelegate(withdrawShares) { - LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceAddress, users.delegator); + LinkedList.List memory thawingRequests = staking.getThawRequestList( + users.indexer, + subgraphDataServiceAddress, + users.delegator + ); ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); skip(thawRequest.thawingUntil + 1); @@ -62,12 +70,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { function testWithdrawDelegation_RevertWhen_NotThawing( uint256 delegationAmount - ) - public - useIndexer - useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) - useDelegation(delegationAmount) - { + ) public useIndexer useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); @@ -100,7 +103,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { { uint256 previousBalance = token.balanceOf(users.delegator); _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); - + // Nothing changed since thawing period haven't finished uint256 newBalance = token.balanceOf(users.delegator); assertEq(newBalance, previousBalance); @@ -120,7 +123,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { uint256 previousBalance = token.balanceOf(users.delegator); _withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); - + uint256 newBalance = token.balanceOf(users.delegator); assertEq(newBalance, previousBalance); @@ -134,10 +137,19 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { resetPrank(users.delegator); _delegate(users.indexer, delegationAmount); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, true); + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + true + ); _undelegate(users.indexer, delegation.shares); - LinkedList.List memory thawingRequests = staking.getThawRequestList(users.indexer, subgraphDataServiceLegacyAddress, users.delegator); + LinkedList.List memory thawingRequests = staking.getThawRequestList( + users.indexer, + subgraphDataServiceLegacyAddress, + users.delegator + ); ThawRequest memory thawRequest = staking.getThawRequest(thawingRequests.tail); skip(thawRequest.thawingUntil + 1); @@ -149,26 +161,70 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { uint256 tokens, uint256 delegationTokens ) public useIndexer useProvision(tokens, 0, MAX_THAWING_PERIOD) useDelegationSlashing() { - delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + delegationTokens = bound(delegationTokens, 2, MAX_STAKING_TOKENS); + resetPrank(users.delegator); _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); - DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); - _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares); - skip(MAX_THAWING_PERIOD + 1); + // undelegate some shares + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares / 2); + // slash all of the provision + delegation resetPrank(subgraphDataServiceAddress); _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); - + + // fast forward in time and attempt to withdraw + skip(MAX_THAWING_PERIOD + 1); resetPrank(users.delegator); - vm.expectRevert(abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, - users.indexer, - subgraphDataServiceAddress - )); + vm.expectRevert( + abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, + users.indexer, + subgraphDataServiceAddress + ) + ); staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); } + function testWithdrawDelegation_AfterRecoveringPool( + uint256 tokens + ) public useIndexer useProvision(tokens, 0, MAX_THAWING_PERIOD) useDelegationSlashing { + uint256 delegationTokens = MAX_STAKING_TOKENS / 10; + + // delegate + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // undelegate some shares + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares / 2); + + // slash all of the provision + delegation + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + + // recover the delegation pool + resetPrank(users.indexer); + token.approve(address(staking), delegationTokens); + _addToDelegationPool(users.indexer, subgraphDataServiceAddress, delegationTokens); + + // fast forward in time and withdraw - this withdraw will net 0 tokens + skip(MAX_THAWING_PERIOD + 1); + resetPrank(users.delegator); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); + } + function testWithdrawDelegation_WithBeneficiary( uint256 delegationAmount, address beneficiary @@ -223,4 +279,4 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 1); } -} \ No newline at end of file +} diff --git a/packages/horizon/test/staking/provision/deprovision.t.sol b/packages/horizon/test/staking/provision/deprovision.t.sol index 376b05e14..ff022e1aa 100644 --- a/packages/horizon/test/staking/provision/deprovision.t.sol +++ b/packages/horizon/test/staking/provision/deprovision.t.sol @@ -104,4 +104,49 @@ contract HorizonStakingDeprovisionTest is HorizonStakingTest { _deprovision(users.indexer, subgraphDataServiceAddress, 0); } + + function testDeprovision_AfterProvisionFullySlashed( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + // thaw some funds so there are some shares and tokens thawing + thawAmount = bound(thawAmount, 1, amount); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + + // slash all of it + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, amount, 0); + + // now deprovision + resetPrank(users.indexer); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); + } + + function testDeprovision_AfterResetingThawingPool( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + // thaw some funds so there are some shares and tokens thawing + thawAmount = bound(thawAmount, 1, amount); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + + // slash all of it + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, amount, 0); + + // put some funds back in + resetPrank(users.indexer); + _stake(amount); + _addToProvision(users.indexer, subgraphDataServiceAddress, amount); + + // thaw some funds again + resetPrank(users.indexer); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + + // now deprovision + resetPrank(users.indexer); + _deprovision(users.indexer, subgraphDataServiceAddress, 0); + } } diff --git a/packages/horizon/test/staking/provision/thaw.t.sol b/packages/horizon/test/staking/provision/thaw.t.sol index 3672683ba..c3b4d6903 100644 --- a/packages/horizon/test/staking/provision/thaw.t.sol +++ b/packages/horizon/test/staking/provision/thaw.t.sol @@ -98,4 +98,45 @@ contract HorizonStakingThawTest is HorizonStakingTest { vm.expectRevert(expectedError); staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); } + + function testThaw_RevertWhen_ProvisionFullySlashed ( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + thawAmount = bound(thawAmount, 1, amount); + + // slash all of it + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, amount, 0); + + // Attempt to thaw on a provision that has been fully slashed + resetPrank(users.indexer); + bytes memory expectedError = abi.encodeWithSignature("HorizonStakingInsufficientTokens(uint256,uint256)", 0, thawAmount); + vm.expectRevert(expectedError); + staking.thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + } + + function testThaw_AfterResetingThawingPool( + uint256 amount, + uint64 thawingPeriod, + uint256 thawAmount + ) public useIndexer useProvision(amount, 0, thawingPeriod) { + // thaw some funds so there are some shares thawing and tokens thawing + thawAmount = bound(thawAmount, 1, amount); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + + // slash all of it + resetPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, amount, 0); + + // put some funds back in + resetPrank(users.indexer); + _stake(amount); + _addToProvision(users.indexer, subgraphDataServiceAddress, amount); + + // we should be able to thaw again + resetPrank(users.indexer); + _thaw(users.indexer, subgraphDataServiceAddress, thawAmount); + } } diff --git a/packages/horizon/test/staking/slash/slash.t.sol b/packages/horizon/test/staking/slash/slash.t.sol index 66a645b7a..7c7933419 100644 --- a/packages/horizon/test/staking/slash/slash.t.sol +++ b/packages/horizon/test/staking/slash/slash.t.sol @@ -21,7 +21,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { slashTokens = bound(slashTokens, 1, tokens); uint256 maxVerifierTokens = (slashTokens * maxVerifierCut) / MAX_PPM; vm.assume(verifierCutAmount <= maxVerifierTokens); - + vm.startPrank(subgraphDataServiceAddress); _slash(users.indexer, subgraphDataServiceAddress, slashTokens, verifierCutAmount); } @@ -35,7 +35,7 @@ contract HorizonStakingSlashTest is HorizonStakingTest { slashTokens = bound(slashTokens, 1, tokens); uint256 maxVerifierTokens = (slashTokens * maxVerifierCut) / MAX_PPM; vm.assume(verifierCutAmount > maxVerifierTokens); - + vm.startPrank(subgraphDataServiceAddress); vm.assume(slashTokens > 0); bytes memory expectedError = abi.encodeWithSelector( @@ -89,15 +89,12 @@ contract HorizonStakingSlashTest is HorizonStakingTest { ) public useIndexer useProvision(tokens, MAX_PPM, 0) { delegationTokens = bound(delegationTokens, 0, MAX_STAKING_TOKENS); vm.assume(slashTokens > tokens + delegationTokens); - + vm.startPrank(subgraphDataServiceAddress); _slash(users.indexer, subgraphDataServiceAddress, slashTokens, 0); } - function testSlash_RevertWhen_NoProvision( - uint256 tokens, - uint256 slashTokens - ) public useIndexer useStake(tokens) { + function testSlash_RevertWhen_NoProvision(uint256 tokens, uint256 slashTokens) public useIndexer useStake(tokens) { vm.assume(slashTokens > 0); bytes memory expectedError = abi.encodeWithSelector( IHorizonStakingMain.HorizonStakingInsufficientTokens.selector, @@ -108,4 +105,39 @@ contract HorizonStakingSlashTest is HorizonStakingTest { vm.startPrank(subgraphDataServiceAddress); staking.slash(users.indexer, slashTokens, 0, subgraphDataServiceAddress); } -} \ No newline at end of file + + function testSlash_Everything( + uint256 tokens, + uint256 delegationTokens + ) public useIndexer useProvision(tokens, MAX_PPM, 0) useDelegationSlashing { + delegationTokens = bound(delegationTokens, 1, MAX_STAKING_TOKENS); + + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + vm.startPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + } + + function testSlash_Everything_WithUndelegation( + uint256 tokens + ) public useIndexer useProvision(tokens, MAX_PPM, 0) useDelegationSlashing { + uint256 delegationTokens = MAX_STAKING_TOKENS / 10; + + resetPrank(users.delegator); + _delegate(users.indexer, subgraphDataServiceAddress, delegationTokens, 0); + + // undelegate half shares so we have some thawing shares/tokens + DelegationInternal memory delegation = _getStorage_Delegation( + users.indexer, + subgraphDataServiceAddress, + users.delegator, + false + ); + resetPrank(users.delegator); + _undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares / 2); + + vm.startPrank(subgraphDataServiceAddress); + _slash(users.indexer, subgraphDataServiceAddress, tokens + delegationTokens, 0); + } +} From 0f5ba68b0ad649b376344bf50c8a0928e5ca73ea Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Thu, 10 Oct 2024 03:02:53 +1100 Subject: [PATCH 272/277] chore(Horizon): add redelegate option (#1059) --- .../internal/IHorizonStakingMain.sol | 40 ++++- .../contracts/staking/HorizonStaking.sol | 37 ++++- .../HorizonStakingShared.t.sol | 55 +++++-- .../test/staking/delegation/redelegate.t.sol | 146 ++++++++++++++++++ .../test/staking/delegation/withdraw.t.sol | 85 ++-------- 5 files changed, 269 insertions(+), 94 deletions(-) create mode 100644 packages/horizon/test/staking/delegation/redelegate.t.sol diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 8d047ac1d..b144b0ce6 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -420,6 +420,16 @@ interface IHorizonStakingMain { */ error HorizonStakingInvalidBeneficiaryZeroAddress(); + /** + * @notice Thrown when attempting to redelegate with a serivce provider that is the zero address. + */ + error HorizonStakingInvalidServiceProviderZeroAddress(); + + /** + * @notice Thrown when attempting to redelegate with a verifier that is the zero address. + */ + error HorizonStakingInvalidVerifierZeroAddress(); + // -- Errors: thaw requests -- error HorizonStakingNothingThawing(); @@ -746,7 +756,6 @@ interface IHorizonStakingMain { /** * @notice Withdraw undelegated tokens from a provision after thawing. - * Tokens can be automatically re-delegated to another provision by setting `newServiceProvider`. * @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw * requests in the event that fulfilling all of them results in a gas limit error. * @dev If the delegation pool was completely slashed before withdrawing, calling this function will fulfill @@ -754,20 +763,39 @@ interface IHorizonStakingMain { * * Requirements: * - Must have previously initiated a thaw request using {undelegate}. - * - `newServiceProvider` must either be zero address or have previously provisioned stake to `verifier`. * * Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {DelegatedTokensWithdrawn} events. * * @param serviceProvider The service provider address * @param verifier The verifier address - * @param newServiceProvider The address of a new service provider, if the delegator wants to re-delegate + * @param nThawRequests The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests. + */ + function withdrawDelegated(address serviceProvider, address verifier, uint256 nThawRequests) external; + + /** + * @notice Re-delegate undelegated tokens from a provision after thawing to a `newServiceProvider` and `newVerifier`. + * @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw + * requests in the event that fulfilling all of them results in a gas limit error. + * + * Requirements: + * - Must have previously initiated a thaw request using {undelegate}. + * - `newServiceProvider` and `newVerifier` must not be the zero address. + * - `newServiceProvider` must have previously provisioned stake to `newVerifier`. + * + * Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {DelegatedTokensWithdrawn} events. + * + * @param oldServiceProvider The old service provider address + * @param oldVerifier The old verifier address + * @param newServiceProvider The address of a new service provider + * @param newVerifier The address of a new verifier * @param minSharesForNewProvider The minimum amount of shares to accept for the new service provider * @param nThawRequests The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests. */ - function withdrawDelegated( - address serviceProvider, - address verifier, + function redelegate( + address oldServiceProvider, + address oldVerifier, address newServiceProvider, + address newVerifier, uint256 minSharesForNewProvider, uint256 nThawRequests ) external; diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 476437ffb..c46670dcb 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -319,11 +319,32 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { function withdrawDelegated( address serviceProvider, address verifier, + uint256 nThawRequests + ) external override notPaused { + _withdrawDelegated(serviceProvider, verifier, address(0), address(0), 0, nThawRequests); + } + + /** + * @notice See {IHorizonStakingMain-redelegate}. + */ + function redelegate( + address oldServiceProvider, + address oldVerifier, address newServiceProvider, + address newVerifier, uint256 minSharesForNewProvider, uint256 nThawRequests ) external override notPaused { - _withdrawDelegated(serviceProvider, verifier, newServiceProvider, minSharesForNewProvider, nThawRequests); + require(newServiceProvider != address(0), HorizonStakingInvalidServiceProviderZeroAddress()); + require(newVerifier != address(0), HorizonStakingInvalidVerifierZeroAddress()); + _withdrawDelegated( + oldServiceProvider, + oldVerifier, + newServiceProvider, + newVerifier, + minSharesForNewProvider, + nThawRequests + ); } /** @@ -360,7 +381,14 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { * @notice See {IHorizonStakingMain-withdrawDelegated}. */ function withdrawDelegated(address serviceProvider, address newServiceProvider) external override notPaused { - _withdrawDelegated(serviceProvider, SUBGRAPH_DATA_SERVICE_ADDRESS, newServiceProvider, 0, 0); + _withdrawDelegated( + serviceProvider, + SUBGRAPH_DATA_SERVICE_ADDRESS, + newServiceProvider, + SUBGRAPH_DATA_SERVICE_ADDRESS, + 0, + 0 + ); } /* @@ -851,6 +879,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address _serviceProvider, address _verifier, address _newServiceProvider, + address _newVerifier, uint256 _minSharesForNewProvider, uint256 _nThawRequests ) private { @@ -882,8 +911,8 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { pool.tokensThawing = tokensThawing; if (tokensThawed != 0) { - if (_newServiceProvider != address(0)) { - _delegate(_newServiceProvider, _verifier, tokensThawed, _minSharesForNewProvider); + if (_newServiceProvider != address(0) && _newVerifier != address(0)) { + _delegate(_newServiceProvider, _newVerifier, tokensThawed, _minSharesForNewProvider); } else { _graphToken().pushTokens(msg.sender, tokensThawed); } diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index d6d88283f..1fe4ceba3 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -1004,9 +1004,26 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { } function _withdrawDelegated( + address serviceProvider, + address verifier, + uint256 nThawRequests + ) internal { + __withdrawDelegated( + serviceProvider, + verifier, + address(0), + address(0), + 0, + nThawRequests, + false + ); + } + + function _redelegate( address serviceProvider, address verifier, address newServiceProvider, + address newVerifier, uint256 minSharesForNewProvider, uint256 nThawRequests ) internal { @@ -1014,6 +1031,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { serviceProvider, verifier, newServiceProvider, + newVerifier, minSharesForNewProvider, nThawRequests, false @@ -1021,7 +1039,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { } function _withdrawDelegated(address serviceProvider, address newServiceProvider) internal { - __withdrawDelegated(serviceProvider, subgraphDataServiceLegacyAddress, newServiceProvider, 0, 0, true); + __withdrawDelegated(serviceProvider, subgraphDataServiceLegacyAddress, newServiceProvider, subgraphDataServiceLegacyAddress, 0, 0, true); } struct BeforeValues_WithdrawDelegated { @@ -1045,19 +1063,20 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { address _serviceProvider, address _verifier, address _newServiceProvider, + address _newVerifier, uint256 _minSharesForNewProvider, uint256 _nThawRequests, bool legacy ) private { (, address msgSender, ) = vm.readCallers(); - bool reDelegate = _newServiceProvider != address(0); + bool reDelegate = _newServiceProvider != address(0) && _newVerifier != address(0); // before BeforeValues_WithdrawDelegated memory beforeValues; beforeValues.pool = _getStorage_DelegationPoolInternal(_serviceProvider, _verifier, legacy); - beforeValues.newPool = _getStorage_DelegationPoolInternal(_newServiceProvider, _verifier, legacy); - beforeValues.newDelegation = _getStorage_Delegation(_serviceProvider, _verifier, msgSender, legacy); + beforeValues.newPool = _getStorage_DelegationPoolInternal(_newServiceProvider, _newVerifier, legacy); + beforeValues.newDelegation = _getStorage_Delegation(_newServiceProvider, _newVerifier, msgSender, legacy); beforeValues.thawRequestList = staking.getThawRequestList(_serviceProvider, _verifier, msgSender); beforeValues.senderBalance = token.balanceOf(msgSender); beforeValues.stakingBalance = token.balanceOf(address(staking)); @@ -1095,7 +1114,7 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { if (reDelegate) { emit IHorizonStakingMain.TokensDelegated( _newServiceProvider, - _verifier, + _newVerifier, msgSender, calcValues.tokensThawed ); @@ -1104,25 +1123,33 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest { } } vm.expectEmit(); + emit IHorizonStakingMain.DelegatedTokensWithdrawn( _serviceProvider, _verifier, msgSender, calcValues.tokensThawed ); - staking.withdrawDelegated( - _serviceProvider, - _verifier, - _newServiceProvider, - _minSharesForNewProvider, - _nThawRequests - ); + if (legacy) { + staking.withdrawDelegated(_serviceProvider, _newServiceProvider); + } else if (reDelegate) { + staking.redelegate( + _serviceProvider, + _verifier, + _newServiceProvider, + _newVerifier, + _minSharesForNewProvider, + _nThawRequests + ); + } else { + staking.withdrawDelegated(_serviceProvider, _verifier, _nThawRequests); + } // after AfterValues_WithdrawDelegated memory afterValues; afterValues.pool = _getStorage_DelegationPoolInternal(_serviceProvider, _verifier, legacy); - afterValues.newPool = _getStorage_DelegationPoolInternal(_newServiceProvider, _verifier, legacy); - afterValues.newDelegation = _getStorage_Delegation(_newServiceProvider, _verifier, msgSender, legacy); + afterValues.newPool = _getStorage_DelegationPoolInternal(_newServiceProvider, _newVerifier, legacy); + afterValues.newDelegation = _getStorage_Delegation(_newServiceProvider, _newVerifier, msgSender, legacy); afterValues.thawRequestList = staking.getThawRequestList(_serviceProvider, _verifier, msgSender); afterValues.senderBalance = token.balanceOf(msgSender); afterValues.stakingBalance = token.balanceOf(address(staking)); diff --git a/packages/horizon/test/staking/delegation/redelegate.t.sol b/packages/horizon/test/staking/delegation/redelegate.t.sol new file mode 100644 index 000000000..605e6601f --- /dev/null +++ b/packages/horizon/test/staking/delegation/redelegate.t.sol @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; + +import { HorizonStakingTest } from "../HorizonStaking.t.sol"; + +contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { + + /* + * MODIFIERS + */ + + modifier useUndelegate(uint256 shares) { + resetPrank(users.delegator); + DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false); + shares = bound(shares, 1, delegation.shares); + + _undelegate(users.indexer, subgraphDataServiceAddress, shares); + _; + } + + /* + * HELPERS + */ + + function _setupNewIndexer(uint256 tokens) private returns(address) { + (, address msgSender, ) = vm.readCallers(); + + address newIndexer = createUser("newIndexer"); + vm.startPrank(newIndexer); + _createProvision(newIndexer, subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); + + vm.startPrank(msgSender); + return newIndexer; + } + + function _setupNewIndexerAndVerifier(uint256 tokens) private returns(address, address) { + (, address msgSender,) = vm.readCallers(); + + address newIndexer = createUser("newIndexer"); + address newVerifier = makeAddr("newVerifier"); + vm.startPrank(newIndexer); + _createProvision(newIndexer, newVerifier, tokens, 0, MAX_THAWING_PERIOD); + + vm.startPrank(msgSender); + return (newIndexer, newVerifier); + } + + /* + * TESTS + */ + + function testRedelegate_MoveToNewServiceProvider( + uint256 delegationAmount, + uint256 withdrawShares + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(withdrawShares) + { + skip(MAX_THAWING_PERIOD + 1); + + // Setup new service provider + address newIndexer = _setupNewIndexer(10_000_000 ether); + _redelegate(users.indexer, subgraphDataServiceAddress, newIndexer, subgraphDataServiceAddress, 0, 0); + } + + function testRedelegate_MoveToNewServiceProviderAndNewVerifier( + uint256 delegationAmount, + uint256 withdrawShares + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(withdrawShares) + { + skip(MAX_THAWING_PERIOD + 1); + + // Setup new service provider + (address newIndexer, address newVerifier) = _setupNewIndexerAndVerifier(10_000_000 ether); + _redelegate(users.indexer, subgraphDataServiceAddress, newIndexer, newVerifier, 0, 0); + } + + function testRedelegate_RevertWhen_VerifierZeroAddress( + uint256 delegationAmount + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(delegationAmount) + { + skip(MAX_THAWING_PERIOD + 1); + + // Setup new service provider + address newIndexer = _setupNewIndexer(10_000_000 ether); + vm.expectRevert(abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingInvalidVerifierZeroAddress.selector)); + staking.redelegate(users.indexer, subgraphDataServiceAddress, newIndexer, address(0), 0, 0); + } + + function testRedelegate_RevertWhen_ServiceProviderZeroAddress( + uint256 delegationAmount + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(delegationAmount) + { + skip(MAX_THAWING_PERIOD + 1); + + // Setup new verifier + address newVerifier = makeAddr("newVerifier"); + vm.expectRevert(abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingInvalidServiceProviderZeroAddress.selector)); + staking.redelegate(users.indexer, subgraphDataServiceAddress, address(0), newVerifier, 0, 0); + } + + function testRedelegate_MoveZeroTokensToNewServiceProviderAndVerifier( + uint256 delegationAmount, + uint256 withdrawShares + ) + public + useIndexer + useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) + useDelegation(delegationAmount) + useUndelegate(withdrawShares) + { + // Setup new service provider + (address newIndexer, address newVerifier) = _setupNewIndexerAndVerifier(10_000_000 ether); + + uint256 previousBalance = token.balanceOf(users.delegator); + _redelegate(users.indexer, subgraphDataServiceAddress, newIndexer, newVerifier, 0, 0); + + uint256 newBalance = token.balanceOf(users.delegator); + assertEq(newBalance, previousBalance); + + uint256 delegatedTokens = staking.getDelegatedTokensAvailable(newIndexer, newVerifier); + assertEq(delegatedTokens, 0); + } +} \ No newline at end of file diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index c66126e1c..2b6c7a76d 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -14,8 +14,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { */ modifier useUndelegate(uint256 shares) { - vm.stopPrank(); - vm.startPrank(users.delegator); + resetPrank(users.delegator); DelegationInternal memory delegation = _getStorage_Delegation( users.indexer, subgraphDataServiceAddress, @@ -28,20 +27,6 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { _; } - /* - * HELPERS - */ - function _setupNewIndexer(uint256 tokens) private returns (address) { - (, address msgSender, ) = vm.readCallers(); - - address newIndexer = createUser("newIndexer"); - vm.startPrank(newIndexer); - _createProvision(newIndexer, subgraphDataServiceAddress, tokens, 0, MAX_THAWING_PERIOD); - - vm.startPrank(msgSender); - return newIndexer; - } - /* * TESTS */ @@ -65,7 +50,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { skip(thawRequest.thawingUntil + 1); - _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, 0); } function testWithdrawDelegation_RevertWhen_NotThawing( @@ -73,23 +58,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { ) public useIndexer useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) useDelegation(delegationAmount) { bytes memory expectedError = abi.encodeWithSignature("HorizonStakingNothingThawing()"); vm.expectRevert(expectedError); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); - } - - function testWithdrawDelegation_MoveToNewServiceProvider( - uint256 delegationAmount - ) - public - useIndexer - useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) - useDelegation(delegationAmount) - useUndelegate(delegationAmount) - { - skip(MAX_THAWING_PERIOD + 1); - - // Setup new service provider - address newIndexer = _setupNewIndexer(10_000_000 ether); - _withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, 0); } function testWithdrawDelegation_ZeroTokens( @@ -102,33 +71,11 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useUndelegate(delegationAmount) { uint256 previousBalance = token.balanceOf(users.delegator); - _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); - - // Nothing changed since thawing period haven't finished - uint256 newBalance = token.balanceOf(users.delegator); - assertEq(newBalance, previousBalance); - } - - function testWithdrawDelegation_MoveZeroTokensToNewServiceProvider( - uint256 delegationAmount - ) - public - useIndexer - useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD) - useDelegation(delegationAmount) - useUndelegate(delegationAmount) - { - // Setup new service provider - address newIndexer = _setupNewIndexer(10_000_000 ether); - - uint256 previousBalance = token.balanceOf(users.delegator); - _withdrawDelegated(users.indexer, subgraphDataServiceAddress, newIndexer, 0, 0); - + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, 0); + + // Nothing changed since thawing period hasn't finished uint256 newBalance = token.balanceOf(users.delegator); assertEq(newBalance, previousBalance); - - uint256 delegatedTokens = staking.getDelegatedTokensAvailable(newIndexer, subgraphDataServiceAddress); - assertEq(delegatedTokens, 0); } function testWithdrawDelegation_LegacySubgraphService(uint256 delegationAmount) public useIndexer { @@ -182,14 +129,12 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { // fast forward in time and attempt to withdraw skip(MAX_THAWING_PERIOD + 1); resetPrank(users.delegator); - vm.expectRevert( - abi.encodeWithSelector( - IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, - users.indexer, - subgraphDataServiceAddress - ) - ); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); + vm.expectRevert(abi.encodeWithSelector( + IHorizonStakingMain.HorizonStakingInvalidDelegationPoolState.selector, + users.indexer, + subgraphDataServiceAddress + )); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, 0); } function testWithdrawDelegation_AfterRecoveringPool( @@ -222,7 +167,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { // fast forward in time and withdraw - this withdraw will net 0 tokens skip(MAX_THAWING_PERIOD + 1); resetPrank(users.delegator); - _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 0); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, 0); } function testWithdrawDelegation_WithBeneficiary( @@ -250,7 +195,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { // Beneficiary withdraws delegated tokens resetPrank(beneficiary); - _withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 1); + _withdrawDelegated(users.indexer, subgraphDataServiceAddress, 1); } function testWithdrawDelegation_RevertWhen_PreviousOwnerAttemptsToWithdraw( @@ -277,6 +222,6 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { // Delegator attempts to withdraw delegated tokens, should revert since beneficiary is the thaw request owner bytes memory expectedError = abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingNothingThawing.selector); vm.expectRevert(expectedError); - staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, address(0), 0, 1); + staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, 1); } } From 36b81e3558d5de541eb6cad3ecad95ec4214865e Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 10 Oct 2024 13:38:42 -0300 Subject: [PATCH 273/277] fix: delegation withdraw test and typo in subgraph test name --- packages/horizon/test/staking/delegation/withdraw.t.sol | 1 + .../test/subgraphService/collect/query/query.t.sol | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index 2b6c7a76d..c9aa04dbc 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -208,6 +208,7 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest { useDelegation(delegationAmount) { vm.assume(beneficiary != address(0)); + vm.assume(beneficiary != users.delegator); // Delegator undelegates to beneficiary resetPrank(users.delegator); diff --git a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol index f72885146..99bfab1ca 100644 --- a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol @@ -71,7 +71,7 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { * TESTS */ - function testCollect_QueryFees_ONLY_THIS( + function testCollect_QueryFees( uint256 tokensAllocated, uint256 tokensPayment ) public useIndexer useAllocation(tokensAllocated) { From 516ac3c8b34fa006c7c1f8059cedf3b23eaf3816 Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 10 Oct 2024 13:39:58 -0300 Subject: [PATCH 274/277] chore: added unit tests for PPMMath --- packages/horizon/test/libraries/PPMMath.t.sol | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 packages/horizon/test/libraries/PPMMath.t.sol diff --git a/packages/horizon/test/libraries/PPMMath.t.sol b/packages/horizon/test/libraries/PPMMath.t.sol new file mode 100644 index 000000000..8aff288b5 --- /dev/null +++ b/packages/horizon/test/libraries/PPMMath.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.27; + +import "forge-std/console.sol"; +import { Test } from "forge-std/Test.sol"; +import { PPMMath } from "../../contracts/libraries/PPMMath.sol"; + +contract PPMMathTest is Test { + uint32 private constant MAX_PPM = 1000000; + + function test_mulPPM(uint256 a, uint256 b) public pure { + a = bound(a, 0, MAX_PPM); + b = bound(b, 0, type(uint256).max / MAX_PPM); + + uint256 result = PPMMath.mulPPM(a, b); + assertEq(result, (a * b) / MAX_PPM); + } + + function test_mulPPMRoundUp(uint256 a, uint256 b) public pure { + a = bound(a, 0, type(uint256).max / MAX_PPM); + b = bound(b, 0, MAX_PPM); + + uint256 result = PPMMath.mulPPMRoundUp(a, b); + assertEq(result, a - PPMMath.mulPPM(a, MAX_PPM - b)); + } + + function test_isValidPPM(uint256 value) public pure { + bool result = PPMMath.isValidPPM(value); + assert(result == (value <= MAX_PPM)); + } + + function test_mullPPM_RevertWhen_InvalidPPM(uint256 a, uint256 b) public { + a = bound(a, MAX_PPM + 1, type(uint256).max); + b = bound(b, MAX_PPM + 1, type(uint256).max); + bytes memory expectedError = abi.encodeWithSelector(PPMMath.PPMMathInvalidMulPPM.selector, a, b); + vm.expectRevert(expectedError); + PPMMath.mulPPM(a, b); + } + + function test_mullPPMRoundUp_RevertWhen_InvalidPPM(uint256 a, uint256 b) public { + b = bound(b, MAX_PPM + 1, type(uint256).max); + bytes memory expectedError = abi.encodeWithSelector(PPMMath.PPMMathInvalidPPM.selector, b); + vm.expectRevert(expectedError); + PPMMath.mulPPMRoundUp(a, b); + } +} From 971a5c5afd1a6caa88568932c68799cda3c87cab Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 10 Oct 2024 14:02:46 -0300 Subject: [PATCH 275/277] chore: added unit tests for TAPCollector --- packages/horizon/test/GraphBase.t.sol | 5 + .../horizon/test/escrow/GraphEscrow.t.sol | 12 +- packages/horizon/test/escrow/collect.t.sol | 6 +- packages/horizon/test/escrow/collector.t.sol | 17 +- .../horizon/test/payments/TAPCollector.t.sol | 167 ++++++++++++++++++ .../PaymentsEscrowShared.t.sol | 43 +++++ 6 files changed, 223 insertions(+), 27 deletions(-) create mode 100644 packages/horizon/test/payments/TAPCollector.t.sol create mode 100644 packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index f02733525..16c89e5c5 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -11,6 +11,7 @@ import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/trans import { PaymentsEscrow } from "contracts/payments/PaymentsEscrow.sol"; import { GraphPayments } from "contracts/payments/GraphPayments.sol"; +import { TAPCollector } from "contracts/payments/collectors/TAPCollector.sol"; import { IHorizonStaking } from "contracts/interfaces/IHorizonStaking.sol"; import { HorizonStaking } from "contracts/staking/HorizonStaking.sol"; import { HorizonStakingExtension } from "contracts/staking/HorizonStakingExtension.sol"; @@ -39,6 +40,7 @@ abstract contract GraphBaseTest is IHorizonStakingTypes, Utils, Constants { EpochManagerMock public epochManager; RewardsManagerMock public rewardsManager; CurationMock public curation; + TAPCollector tapCollector; HorizonStaking private stakingBase; HorizonStakingExtension private stakingExtension; @@ -84,6 +86,7 @@ abstract contract GraphBaseTest is IHorizonStakingTypes, Utils, Constants { vm.label({ account: address(escrow), newLabel: "PaymentsEscrow" }); vm.label({ account: address(staking), newLabel: "HorizonStaking" }); vm.label({ account: address(stakingExtension), newLabel: "HorizonStakingExtension" }); + vm.label({ account: address(tapCollector), newLabel: "TAPCollector" }); // Ensure caller is back to the original msg.sender vm.stopPrank(); @@ -182,6 +185,8 @@ abstract contract GraphBaseTest is IHorizonStakingTypes, Utils, Constants { subgraphDataServiceLegacyAddress ); + tapCollector = new TAPCollector("TAPCollector", "1", address(controller)); + resetPrank(users.governor); proxyAdmin.upgrade(stakingProxy, address(stakingBase)); proxyAdmin.acceptProxy(stakingBase, stakingProxy); diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index 75d0b55ae..a472162e9 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -4,8 +4,9 @@ pragma solidity 0.8.27; import "forge-std/Test.sol"; import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; +import { PaymentsEscrowSharedTest } from "../shared/payments-escrow/PaymentsEscrowShared.t.sol"; -contract GraphEscrowTest is HorizonStakingSharedTest { +contract GraphEscrowTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest { /* * MODIFIERS @@ -25,7 +26,7 @@ contract GraphEscrowTest is HorizonStakingSharedTest { modifier useDeposit(uint256 tokens) { vm.assume(tokens > 0); vm.assume(tokens <= MAX_STAKING_TOKENS); - _depositTokens(tokens); + _depositTokens(users.verifier, users.indexer, tokens); _; } @@ -38,7 +39,7 @@ contract GraphEscrowTest is HorizonStakingSharedTest { modifier depositAndThawTokens(uint256 amount, uint256 thawAmount) { vm.assume(thawAmount > 0); vm.assume(amount > thawAmount); - _depositTokens(amount); + _depositTokens(users.verifier, users.indexer, amount); escrow.thaw(users.verifier, users.indexer, thawAmount); _; } @@ -47,11 +48,6 @@ contract GraphEscrowTest is HorizonStakingSharedTest { * HELPERS */ - function _depositTokens(uint256 tokens) internal { - token.approve(address(escrow), tokens); - escrow.deposit(users.verifier, users.indexer, tokens); - } - function _approveEscrow(uint256 tokens) internal { token.approve(address(escrow), tokens); } diff --git a/packages/horizon/test/escrow/collect.t.sol b/packages/horizon/test/escrow/collect.t.sol index db0c2c099..72b795ee9 100644 --- a/packages/horizon/test/escrow/collect.t.sol +++ b/packages/horizon/test/escrow/collect.t.sol @@ -107,7 +107,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { resetPrank(users.gateway); escrow.approveCollector(users.verifier, tokens); - _depositTokens(tokens); + _depositTokens(users.verifier, users.indexer, tokens); resetPrank(users.verifier); _collect(IGraphPayments.PaymentTypes.QueryFee, users.gateway, users.indexer, tokens, subgraphDataServiceAddress, tokensDataService); @@ -163,7 +163,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { resetPrank(users.gateway); escrow.approveCollector(users.verifier, amount); - _depositTokens(amount); + _depositTokens(users.verifier, users.indexer, amount); resetPrank(users.verifier); vm.expectRevert(abi.encodeWithSelector( @@ -182,7 +182,7 @@ contract GraphEscrowCollectTest is GraphEscrowTest { resetPrank(users.gateway); escrow.approveCollector(users.verifier, amount); - _depositTokens(amount); + _depositTokens(users.verifier, users.indexer, amount); resetPrank(users.verifier); vm.expectRevert(abi.encodeWithSelector( diff --git a/packages/horizon/test/escrow/collector.t.sol b/packages/horizon/test/escrow/collector.t.sol index ed5c05384..d6cb3bc0f 100644 --- a/packages/horizon/test/escrow/collector.t.sol +++ b/packages/horizon/test/escrow/collector.t.sol @@ -13,21 +13,6 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { * HELPERS */ - function _approveCollector(uint256 tokens) internal { - (uint256 beforeAllowance,) = escrow.authorizedCollectors(users.gateway, users.verifier); - vm.expectEmit(address(escrow)); - emit IPaymentsEscrow.AuthorizedCollector( - users.gateway, // payer - users.verifier, // collector - tokens, // addedAllowance - beforeAllowance + tokens // newTotalAllowance after the added allowance - ); - escrow.approveCollector(users.verifier, tokens); - (uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(users.gateway, users.verifier); - assertEq(allowance - beforeAllowance, tokens); - assertEq(thawEndTimestamp, 0); - } - function _thawCollector() internal { (uint256 beforeAllowance,) = escrow.authorizedCollectors(users.gateway, users.verifier); vm.expectEmit(address(escrow)); @@ -74,7 +59,7 @@ contract GraphEscrowCollectorTest is GraphEscrowTest { uint256 approveTokens = tokens / approveSteps; for (uint i = 0; i < approveSteps; i++) { - _approveCollector(approveTokens); + _approveCollector(users.verifier, approveTokens); } } diff --git a/packages/horizon/test/payments/TAPCollector.t.sol b/packages/horizon/test/payments/TAPCollector.t.sol new file mode 100644 index 000000000..e1c177282 --- /dev/null +++ b/packages/horizon/test/payments/TAPCollector.t.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; +import { ITAPCollector } from "../../contracts/interfaces/ITAPCollector.sol"; +import { IPaymentsCollector } from "../../contracts/interfaces/IPaymentsCollector.sol"; +import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; +import { TAPCollector } from "../../contracts/payments/collectors/TAPCollector.sol"; +import { PPMMath } from "../../contracts/libraries/PPMMath.sol"; + +import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; +import { PaymentsEscrowSharedTest } from "../shared/payments-escrow/PaymentsEscrowShared.t.sol"; + +contract TAPCollectorTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest { + using PPMMath for uint256; + + address payer; + uint256 payerPrivateKey; + + /* + * HELPERS + */ + + function _getQueryFeeEncodedData(address indexer, address collector, uint128 tokens) private view returns (bytes memory) { + ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(indexer, collector, tokens); + bytes32 messageHash = tapCollector.encodeRAV(rav); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(payerPrivateKey, messageHash); + bytes memory signature = abi.encodePacked(r, s, v); + ITAPCollector.SignedRAV memory signedRAV = ITAPCollector.SignedRAV(rav, signature); + return abi.encode(signedRAV); + } + + function _getRAV( + address indexer, + address collector, + uint128 tokens + ) private pure returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { + return + ITAPCollector.ReceiptAggregateVoucher({ + dataService: collector, + serviceProvider: indexer, + timestampNs: 0, + valueAggregate: tokens, + metadata: abi.encode("") + }); + } + + function _collect(IGraphPayments.PaymentTypes _paymentType, bytes memory _data) private { + (ITAPCollector.SignedRAV memory signedRAV, uint256 dataServiceCut) = abi.decode(_data, (ITAPCollector.SignedRAV, uint256)); + bytes32 messageHash = tapCollector.encodeRAV(signedRAV.rav); + address _payer = ECDSA.recover(messageHash, signedRAV.signature); + uint256 tokensAlreadyCollected = tapCollector.tokensCollected(signedRAV.rav.dataService, signedRAV.rav.serviceProvider, _payer); + uint256 tokensToCollect = signedRAV.rav.valueAggregate - tokensAlreadyCollected; + uint256 tokensDataService = tokensToCollect.mulPPM(dataServiceCut); + + vm.expectEmit(address(tapCollector)); + emit IPaymentsCollector.PaymentCollected( + _paymentType, + _payer, + signedRAV.rav.serviceProvider, + tokensToCollect, + signedRAV.rav.dataService, + tokensDataService + ); + emit ITAPCollector.RAVCollected( + _payer, + signedRAV.rav.dataService, + signedRAV.rav.serviceProvider, + signedRAV.rav.timestampNs, + signedRAV.rav.valueAggregate, + signedRAV.rav.metadata, + signedRAV.signature + ); + + uint256 tokensCollected = tapCollector.collect(_paymentType, _data); + assertEq(tokensCollected, tokensToCollect); + + uint256 tokensCollectedAfter = tapCollector.tokensCollected(signedRAV.rav.dataService, signedRAV.rav.serviceProvider, _payer); + assertEq(tokensCollectedAfter, signedRAV.rav.valueAggregate); + } + + /* + * SET UP + */ + + function setUp() public virtual override { + super.setUp(); + (payer, payerPrivateKey) = makeAddrAndKey("payer"); + vm.label({ account: payer, newLabel: "payer" }); + deal({ token: address(token), to: payer, give: type(uint256).max }); + } + + /* + * TESTS + */ + + function testCollect(uint256 tokens) public { + tokens = bound(tokens, 1, type(uint128).max); + + resetPrank(payer); + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testCollect_Multiple(uint256 tokens, uint8 steps) public { + steps = uint8(bound(steps, 1, 100)); + tokens = bound(tokens, steps, type(uint128).max); + + resetPrank(payer); + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + resetPrank(users.verifier); + uint256 payed = 0; + uint256 tokensPerStep = tokens / steps; + for (uint256 i = 0; i < steps; i++) { + bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(payed + tokensPerStep)); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + payed += tokensPerStep; + } + } + + function testCollect_RevertWhen_CallerNotDataService(uint256 tokens) public { + tokens = bound(tokens, 1, type(uint128).max); + + resetPrank(payer); + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.indexer); + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorCallerNotDataService.selector, + users.indexer, + users.verifier + ); + vm.expectRevert(expectedError); + tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testCollect_RevertWhen_InconsistentRAVTokens(uint256 tokens) public { + tokens = bound(tokens, 1, type(uint128).max); + + resetPrank(payer); + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + + // Attempt to collect again + vm.expectRevert(abi.encodeWithSelector( + ITAPCollector.TAPCollectorInconsistentRAVTokens.selector, + tokens, + tokens + )); + tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); + } +} diff --git a/packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol b/packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol new file mode 100644 index 000000000..b7ee76839 --- /dev/null +++ b/packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { IPaymentsEscrow } from "../../../contracts/interfaces/IPaymentsEscrow.sol"; +import { GraphBaseTest } from "../../GraphBase.t.sol"; + +abstract contract PaymentsEscrowSharedTest is GraphBaseTest { + + /* + * HELPERS + */ + + function _approveCollector(address _verifier, uint256 _tokens) internal { + (, address msgSender, ) = vm.readCallers(); + (uint256 beforeAllowance,) = escrow.authorizedCollectors(msgSender, _verifier); + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.AuthorizedCollector( + msgSender, // payer + _verifier, // collector + _tokens, // addedAllowance + beforeAllowance + _tokens // newTotalAllowance after the added allowance + ); + escrow.approveCollector(_verifier, _tokens); + (uint256 allowance, uint256 thawEndTimestamp) = escrow.authorizedCollectors(msgSender, _verifier); + assertEq(allowance - beforeAllowance, _tokens); + assertEq(thawEndTimestamp, 0); + } + + function _depositTokens(address _collector, address _receiver, uint256 _tokens) internal { + (, address msgSender, ) = vm.readCallers(); + (uint256 escrowBalanceBefore,,) = escrow.escrowAccounts(msgSender, _collector, _receiver); + token.approve(address(escrow), _tokens); + + vm.expectEmit(address(escrow)); + emit IPaymentsEscrow.Deposit(msgSender, _collector, _receiver, _tokens); + escrow.deposit(_collector, _receiver, _tokens); + + (uint256 escrowBalanceAfter,,) = escrow.escrowAccounts(msgSender, _collector, _receiver); + assertEq(escrowBalanceAfter - _tokens, escrowBalanceBefore); + } +} From 504fff197f07b27e82bb0dd2a1f63061f42eb490 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:28:06 +1100 Subject: [PATCH 276/277] chore(Horizon): add signers to TAPCollector (#1060) * chore(Horizon): add signers to TAPCollector * fix: collect multiple queries test * fix: rename events and change parameter order to make it consistent * fix: lint issues * chore: add tap collector signer unit tests --- .../interfaces/IPaymentsCollector.sol | 3 + .../contracts/interfaces/ITAPCollector.sol | 131 +++++++++++++ .../payments/collectors/TAPCollector.sol | 168 +++++++++++++--- packages/horizon/test/GraphBase.t.sol | 2 +- .../horizon/test/escrow/GraphEscrow.t.sol | 6 - .../horizon/test/payments/TAPCollector.t.sol | 167 ---------------- .../payments/tap-collector/TAPCollector.t.sol | 148 ++++++++++++++ .../tap-collector/collect/collect.t.sol | 180 ++++++++++++++++++ .../signer/authorizeSigner.t.sol | 66 +++++++ .../signer/cancelThawSigner.t.sol | 39 ++++ .../tap-collector/signer/revokeSigner.t.sol | 54 ++++++ .../tap-collector/signer/thawSigner.t.sol | 29 +++ .../PaymentsEscrowShared.t.sol | 10 + packages/horizon/test/utils/Constants.sol | 2 + .../test/SubgraphBaseTest.t.sol | 2 +- .../subgraphService/SubgraphService.t.sol | 2 +- .../subgraphService/collect/query/query.t.sol | 31 ++- .../subgraph-service/test/utils/Constants.sol | 2 + 18 files changed, 827 insertions(+), 215 deletions(-) delete mode 100644 packages/horizon/test/payments/TAPCollector.t.sol create mode 100644 packages/horizon/test/payments/tap-collector/TAPCollector.t.sol create mode 100644 packages/horizon/test/payments/tap-collector/collect/collect.t.sol create mode 100644 packages/horizon/test/payments/tap-collector/signer/authorizeSigner.t.sol create mode 100644 packages/horizon/test/payments/tap-collector/signer/cancelThawSigner.t.sol create mode 100644 packages/horizon/test/payments/tap-collector/signer/revokeSigner.t.sol create mode 100644 packages/horizon/test/payments/tap-collector/signer/thawSigner.t.sol diff --git a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol index bcd67df0a..85d09d59f 100644 --- a/packages/horizon/contracts/interfaces/IPaymentsCollector.sol +++ b/packages/horizon/contracts/interfaces/IPaymentsCollector.sol @@ -36,6 +36,9 @@ interface IPaymentsCollector { * @notice Initiate a payment collection through the payments protocol * @dev This function should require the caller to present some form of evidence of the payer's debt to * the receiver. The collector should validate this evidence and, if valid, collect the payment. + * Requirements: + * - The caller must be the data service the RAV was issued to + * - The signer of the RAV must be authorized to sign for the payer * * Emits a {PaymentCollected} event * diff --git a/packages/horizon/contracts/interfaces/ITAPCollector.sol b/packages/horizon/contracts/interfaces/ITAPCollector.sol index 72a8dc0bc..dd557de53 100644 --- a/packages/horizon/contracts/interfaces/ITAPCollector.sol +++ b/packages/horizon/contracts/interfaces/ITAPCollector.sol @@ -11,6 +11,15 @@ import { IPaymentsCollector } from "./IPaymentsCollector.sol"; * payments using a TAP RAV (Receipt Aggregate Voucher). */ interface ITAPCollector is IPaymentsCollector { + /// @notice Details for a payer-signer pair + /// @dev Signers can be removed only after a thawing period + struct PayerAuthorization { + // Payer the signer is authorized to sign for + address payer; + // Timestamp at which thawing period ends (zero if not thawing) + uint256 thawEndTimestamp; + } + /// @notice The Receipt Aggregate Voucher (RAV) struct struct ReceiptAggregateVoucher { // The address of the data service the RAV was issued to @@ -34,6 +43,36 @@ interface ITAPCollector is IPaymentsCollector { bytes signature; } + /** + * @notice Emitted when a signer is authorized to sign RAVs for a payer + * @param payer The address of the payer authorizing the signer + * @param authorizedSigner The address of the authorized signer + */ + event SignerAuthorized(address indexed payer, address indexed authorizedSigner); + + /** + * @notice Emitted when a signer is thawed to be removed from the authorized signers list + * @param payer The address of the payer thawing the signer + * @param authorizedSigner The address of the signer to thaw + * @param thawEndTimestamp The timestamp at which the thawing period ends + */ + event SignerThawing(address indexed payer, address indexed authorizedSigner, uint256 thawEndTimestamp); + + /** + * @dev Emitted when the thawing of a signer is cancelled + * @param payer The address of the payer cancelling the thawing + * @param authorizedSigner The address of the authorized signer + * @param thawEndTimestamp The timestamp at which the thawing period ends + */ + event SignerThawCanceled(address indexed payer, address indexed authorizedSigner, uint256 thawEndTimestamp); + + /** + * @dev Emitted when a authorized signer has been revoked + * @param payer The address of the payer revoking the signer + * @param authorizedSigner The address of the authorized signer + */ + event SignerRevoked(address indexed payer, address indexed authorizedSigner); + /** * @notice Emitted when a RAV is collected * @param payer The address of the payer @@ -54,6 +93,50 @@ interface ITAPCollector is IPaymentsCollector { bytes signature ); + /** + * Thrown when the signer is already authorized + * @param authorizingPayer The address of the payer authorizing the signer + * @param signer The address of the signer + */ + error TAPCollectorSignerAlreadyAuthorized(address authorizingPayer, address signer); + + /** + * Thrown when the signer proof deadline is invalid + * @param proofDeadline The deadline for the proof provided by the signer + * @param currentTimestamp The current timestamp + */ + error TAPCollectorInvalidSignerProofDeadline(uint256 proofDeadline, uint256 currentTimestamp); + + /** + * Thrown when the signer proof is invalid + */ + error TAPCollectorInvalidSignerProof(); + + /** + * Thrown when the signer is not authorized by the payer + * @param payer The address of the payer + * @param signer The address of the signer + */ + error TAPCollectorSignerNotAuthorizedByPayer(address payer, address signer); + + /** + * Thrown when the signer is not thawing + * @param signer The address of the signer + */ + error TAPCollectorSignerNotThawing(address signer); + + /** + * Thrown when the signer is still thawing + * @param currentTimestamp The current timestamp + * @param thawEndTimestamp The timestamp at which the thawing period ends + */ + error TAPCollectorSignerStillThawing(uint256 currentTimestamp, uint256 thawEndTimestamp); + + /** + * Thrown when the RAV signer is invalid + */ + error TAPCollectorInvalidRAVSigner(); + /** * Thrown when the caller is not the data service the RAV was issued to * @param caller The address of the caller @@ -69,6 +152,54 @@ interface ITAPCollector is IPaymentsCollector { */ error TAPCollectorInconsistentRAVTokens(uint256 tokens, uint256 tokensCollected); + /** + * @notice Authorize a signer to sign on behalf of the payer + * @dev Requirements: + * - `signer` must not be already authorized + * - `proofDeadline` must be greater than the current timestamp + * - `proof` must be a valid signature from the signer being authorized + * + * Emits an {SignerAuthorized} event + * @param signer The addres of the authorized signer + * @param proofDeadline The deadline for the proof provided by the signer + * @param proof The proof provided by the signer to be authorized by the payer, consists of (chainID, proof deadline, sender address) + */ + function authorizeSigner(address signer, uint256 proofDeadline, bytes calldata proof) external; + + /** + * @notice Starts thawing a signer to be removed from the authorized signers list + * @dev Thawing a signer alerts receivers that signatures from that signer will soon be deemed invalid. + * Receivers without existing signed receipts or RAVs from this signer should treat them as unauthorized. + * Those with existing signed documents from this signer should work towards settling their engagements. + * Once a signer is thawed, they should be viewed as revoked regardless of their revocation status. + * Requirements: + * - `signer` must be authorized by the payer calling this function + * + * Emits a {SignerThawing} event + * @param signer The address of the signer to thaw + */ + function thawSigner(address signer) external; + + /** + * @notice Stops thawing a signer. + * @dev Requirements: + * - `signer` must be thawing and authorized by the payer calling this function + * + * Emits a {SignerThawCanceled} event + * @param signer The address of the signer to cancel thawing + */ + function cancelThawSigner(address signer) external; + + /** + * @notice Revokes a signer from the authorized signers list if thawed. + * @dev Requirements: + * - `signer` must be thawed and authorized by the payer calling this function + * + * Emits a {SignerRevoked} event + * @param signer The address of the signer + */ + function revokeAuthorizedSigner(address signer) external; + /** * @dev Recovers the signer address of a signed ReceiptAggregateVoucher (RAV). * @param signedRAV The SignedRAV containing the RAV and its signature. diff --git a/packages/horizon/contracts/payments/collectors/TAPCollector.sol b/packages/horizon/contracts/payments/collectors/TAPCollector.sol index 91293af09..57588a042 100644 --- a/packages/horizon/contracts/payments/collectors/TAPCollector.sol +++ b/packages/horizon/contracts/payments/collectors/TAPCollector.sol @@ -9,6 +9,7 @@ import { PPMMath } from "../../libraries/PPMMath.sol"; import { GraphDirectory } from "../../utilities/GraphDirectory.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; /** * @title TAPCollector contract @@ -29,21 +30,89 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { "ReceiptAggregateVoucher(address dataService,address serviceProvider,uint64 timestampNs,uint128 valueAggregate,bytes metadata)" ); + /// @notice Authorization details for payer-signer pairs + mapping(address signer => PayerAuthorization authorizedSigner) public authorizedSigners; + /// @notice Tracks the amount of tokens already collected by a data service from a payer to a receiver mapping(address dataService => mapping(address receiver => mapping(address payer => uint256 tokens))) public tokensCollected; + /// @notice The duration (in seconds) in which a signer is thawing before they can be revoked + uint256 public immutable REVOKE_SIGNER_THAWING_PERIOD; + /** * @notice Constructs a new instance of the TAPVerifier contract. * @param eip712Name The name of the EIP712 domain. * @param eip712Version The version of the EIP712 domain. * @param controller The address of the Graph controller. + * @param revokeSignerThawingPeriod The duration (in seconds) in which a signer is thawing before they can be revoked. */ constructor( string memory eip712Name, string memory eip712Version, - address controller - ) EIP712(eip712Name, eip712Version) GraphDirectory(controller) {} + address controller, + uint256 revokeSignerThawingPeriod + ) EIP712(eip712Name, eip712Version) GraphDirectory(controller) { + REVOKE_SIGNER_THAWING_PERIOD = revokeSignerThawingPeriod; + } + + /** + * See {ITAPCollector.authorizeSigner}. + */ + function authorizeSigner(address signer, uint256 proofDeadline, bytes calldata proof) external override { + require( + authorizedSigners[signer].payer == address(0), + TAPCollectorSignerAlreadyAuthorized(authorizedSigners[signer].payer, signer) + ); + + _verifyAuthorizedSignerProof(proof, proofDeadline, signer); + + authorizedSigners[signer].payer = msg.sender; + authorizedSigners[signer].thawEndTimestamp = 0; + emit SignerAuthorized(msg.sender, signer); + } + + /** + * See {ITAPCollector.thawSigner}. + */ + function thawSigner(address signer) external override { + PayerAuthorization storage authorization = authorizedSigners[signer]; + + require(authorization.payer == msg.sender, TAPCollectorSignerNotAuthorizedByPayer(msg.sender, signer)); + + authorization.thawEndTimestamp = block.timestamp + REVOKE_SIGNER_THAWING_PERIOD; + emit SignerThawing(msg.sender, signer, authorization.thawEndTimestamp); + } + + /** + * See {ITAPCollector.cancelThawSigner}. + */ + function cancelThawSigner(address signer) external override { + PayerAuthorization storage authorization = authorizedSigners[signer]; + + require(authorization.payer == msg.sender, TAPCollectorSignerNotAuthorizedByPayer(msg.sender, signer)); + require(authorization.thawEndTimestamp > 0, TAPCollectorSignerNotThawing(signer)); + + authorization.thawEndTimestamp = 0; + emit SignerThawCanceled(msg.sender, signer, 0); + } + + /** + * See {ITAPCollector.revokeAuthorizedSigner}. + */ + function revokeAuthorizedSigner(address signer) external override { + PayerAuthorization storage authorization = authorizedSigners[signer]; + + require(authorization.payer == msg.sender, TAPCollectorSignerNotAuthorizedByPayer(msg.sender, signer)); + require(authorization.thawEndTimestamp > 0, TAPCollectorSignerNotThawing(signer)); + require( + authorization.thawEndTimestamp <= block.timestamp, + TAPCollectorSignerStillThawing(block.timestamp, authorization.thawEndTimestamp) + ); + + delete authorizedSigners[signer]; + emit SignerRevoked(msg.sender, signer); + } /** * @notice Initiate a payment collection through the payments protocol @@ -58,59 +127,73 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { TAPCollectorCallerNotDataService(msg.sender, signedRAV.rav.dataService) ); - address dataService = signedRAV.rav.dataService; - address payer = _recoverRAVSigner(signedRAV); - address receiver = signedRAV.rav.serviceProvider; + address signer = _recoverRAVSigner(signedRAV); + require(authorizedSigners[signer].payer != address(0), TAPCollectorInvalidRAVSigner()); + + return _collect(paymentType, authorizedSigners[signer].payer, signedRAV, dataServiceCut); + } + + /** + * @notice See {ITAPCollector.recoverRAVSigner} + */ + function recoverRAVSigner(SignedRAV calldata signedRAV) external view override returns (address) { + return _recoverRAVSigner(signedRAV); + } + + /** + * @notice See {ITAPCollector.encodeRAV} + */ + function encodeRAV(ReceiptAggregateVoucher calldata rav) external view returns (bytes32) { + return _encodeRAV(rav); + } - uint256 tokensRAV = signedRAV.rav.valueAggregate; - uint256 tokensAlreadyCollected = tokensCollected[dataService][receiver][payer]; + /** + * @notice See {ITAPCollector.collect} + */ + function _collect( + IGraphPayments.PaymentTypes _paymentType, + address _payer, + SignedRAV memory _signedRAV, + uint256 _dataServiceCut + ) private returns (uint256) { + address dataService = _signedRAV.rav.dataService; + address receiver = _signedRAV.rav.serviceProvider; + + uint256 tokensRAV = _signedRAV.rav.valueAggregate; + uint256 tokensAlreadyCollected = tokensCollected[dataService][receiver][_payer]; require( tokensRAV > tokensAlreadyCollected, TAPCollectorInconsistentRAVTokens(tokensRAV, tokensAlreadyCollected) ); uint256 tokensToCollect = tokensRAV - tokensAlreadyCollected; - uint256 tokensDataService = tokensToCollect.mulPPM(dataServiceCut); + uint256 tokensDataService = tokensToCollect.mulPPM(_dataServiceCut); if (tokensToCollect > 0) { + tokensCollected[dataService][receiver][_payer] = tokensRAV; _graphPaymentsEscrow().collect( - paymentType, - payer, + _paymentType, + _payer, receiver, tokensToCollect, dataService, tokensDataService ); - tokensCollected[dataService][receiver][payer] = tokensRAV; } - emit PaymentCollected(paymentType, payer, receiver, tokensToCollect, dataService, tokensDataService); + emit PaymentCollected(_paymentType, _payer, receiver, tokensToCollect, dataService, tokensDataService); emit RAVCollected( - payer, + _payer, dataService, receiver, - signedRAV.rav.timestampNs, - signedRAV.rav.valueAggregate, - signedRAV.rav.metadata, - signedRAV.signature + _signedRAV.rav.timestampNs, + _signedRAV.rav.valueAggregate, + _signedRAV.rav.metadata, + _signedRAV.signature ); return tokensToCollect; } - /** - * @notice See {ITAPCollector.recoverRAVSigner} - */ - function recoverRAVSigner(SignedRAV calldata signedRAV) external view override returns (address) { - return _recoverRAVSigner(signedRAV); - } - - /** - * @notice See {ITAPCollector.encodeRAV} - */ - function encodeRAV(ReceiptAggregateVoucher calldata rav) external view returns (bytes32) { - return _encodeRAV(rav); - } - /** * @notice See {ITAPCollector.recoverRAVSigner} */ @@ -137,4 +220,27 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector { ) ); } + + /** + * @notice Verify the proof provided by the payer authorizing the signer + * @param _proof The proof provided by the payer authorizing the signer + * @param _proofDeadline The deadline by which the proof must be verified + * @param _signer The signer to be authorized + */ + function _verifyAuthorizedSignerProof(bytes calldata _proof, uint256 _proofDeadline, address _signer) private view { + // Verify that the proofDeadline has not passed + require( + _proofDeadline > block.timestamp, + TAPCollectorInvalidSignerProofDeadline(_proofDeadline, block.timestamp) + ); + + // Generate the hash of the payer's address + bytes32 messageHash = keccak256(abi.encodePacked(block.chainid, _proofDeadline, msg.sender)); + + // Generate the digest to be signed by the signer + bytes32 digest = MessageHashUtils.toEthSignedMessageHash(messageHash); + + // Verify that the recovered signer matches the expected signer + require(ECDSA.recover(digest, _proof) == _signer, TAPCollectorInvalidSignerProof()); + } } diff --git a/packages/horizon/test/GraphBase.t.sol b/packages/horizon/test/GraphBase.t.sol index 16c89e5c5..7aa44d6f5 100644 --- a/packages/horizon/test/GraphBase.t.sol +++ b/packages/horizon/test/GraphBase.t.sol @@ -185,7 +185,7 @@ abstract contract GraphBaseTest is IHorizonStakingTypes, Utils, Constants { subgraphDataServiceLegacyAddress ); - tapCollector = new TAPCollector("TAPCollector", "1", address(controller)); + tapCollector = new TAPCollector("TAPCollector", "1", address(controller), revokeSignerThawingPeriod); resetPrank(users.governor); proxyAdmin.upgrade(stakingProxy, address(stakingBase)); diff --git a/packages/horizon/test/escrow/GraphEscrow.t.sol b/packages/horizon/test/escrow/GraphEscrow.t.sol index a472162e9..d3ffd21da 100644 --- a/packages/horizon/test/escrow/GraphEscrow.t.sol +++ b/packages/horizon/test/escrow/GraphEscrow.t.sol @@ -12,12 +12,6 @@ contract GraphEscrowTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest { * MODIFIERS */ - modifier useGateway() { - vm.startPrank(users.gateway); - _; - vm.stopPrank(); - } - modifier approveEscrow(uint256 tokens) { _approveEscrow(tokens); _; diff --git a/packages/horizon/test/payments/TAPCollector.t.sol b/packages/horizon/test/payments/TAPCollector.t.sol deleted file mode 100644 index e1c177282..000000000 --- a/packages/horizon/test/payments/TAPCollector.t.sol +++ /dev/null @@ -1,167 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.27; - -import "forge-std/Test.sol"; - -import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import { IHorizonStakingMain } from "../../contracts/interfaces/internal/IHorizonStakingMain.sol"; -import { ITAPCollector } from "../../contracts/interfaces/ITAPCollector.sol"; -import { IPaymentsCollector } from "../../contracts/interfaces/IPaymentsCollector.sol"; -import { IGraphPayments } from "../../contracts/interfaces/IGraphPayments.sol"; -import { TAPCollector } from "../../contracts/payments/collectors/TAPCollector.sol"; -import { PPMMath } from "../../contracts/libraries/PPMMath.sol"; - -import { HorizonStakingSharedTest } from "../shared/horizon-staking/HorizonStakingShared.t.sol"; -import { PaymentsEscrowSharedTest } from "../shared/payments-escrow/PaymentsEscrowShared.t.sol"; - -contract TAPCollectorTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest { - using PPMMath for uint256; - - address payer; - uint256 payerPrivateKey; - - /* - * HELPERS - */ - - function _getQueryFeeEncodedData(address indexer, address collector, uint128 tokens) private view returns (bytes memory) { - ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(indexer, collector, tokens); - bytes32 messageHash = tapCollector.encodeRAV(rav); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(payerPrivateKey, messageHash); - bytes memory signature = abi.encodePacked(r, s, v); - ITAPCollector.SignedRAV memory signedRAV = ITAPCollector.SignedRAV(rav, signature); - return abi.encode(signedRAV); - } - - function _getRAV( - address indexer, - address collector, - uint128 tokens - ) private pure returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { - return - ITAPCollector.ReceiptAggregateVoucher({ - dataService: collector, - serviceProvider: indexer, - timestampNs: 0, - valueAggregate: tokens, - metadata: abi.encode("") - }); - } - - function _collect(IGraphPayments.PaymentTypes _paymentType, bytes memory _data) private { - (ITAPCollector.SignedRAV memory signedRAV, uint256 dataServiceCut) = abi.decode(_data, (ITAPCollector.SignedRAV, uint256)); - bytes32 messageHash = tapCollector.encodeRAV(signedRAV.rav); - address _payer = ECDSA.recover(messageHash, signedRAV.signature); - uint256 tokensAlreadyCollected = tapCollector.tokensCollected(signedRAV.rav.dataService, signedRAV.rav.serviceProvider, _payer); - uint256 tokensToCollect = signedRAV.rav.valueAggregate - tokensAlreadyCollected; - uint256 tokensDataService = tokensToCollect.mulPPM(dataServiceCut); - - vm.expectEmit(address(tapCollector)); - emit IPaymentsCollector.PaymentCollected( - _paymentType, - _payer, - signedRAV.rav.serviceProvider, - tokensToCollect, - signedRAV.rav.dataService, - tokensDataService - ); - emit ITAPCollector.RAVCollected( - _payer, - signedRAV.rav.dataService, - signedRAV.rav.serviceProvider, - signedRAV.rav.timestampNs, - signedRAV.rav.valueAggregate, - signedRAV.rav.metadata, - signedRAV.signature - ); - - uint256 tokensCollected = tapCollector.collect(_paymentType, _data); - assertEq(tokensCollected, tokensToCollect); - - uint256 tokensCollectedAfter = tapCollector.tokensCollected(signedRAV.rav.dataService, signedRAV.rav.serviceProvider, _payer); - assertEq(tokensCollectedAfter, signedRAV.rav.valueAggregate); - } - - /* - * SET UP - */ - - function setUp() public virtual override { - super.setUp(); - (payer, payerPrivateKey) = makeAddrAndKey("payer"); - vm.label({ account: payer, newLabel: "payer" }); - deal({ token: address(token), to: payer, give: type(uint256).max }); - } - - /* - * TESTS - */ - - function testCollect(uint256 tokens) public { - tokens = bound(tokens, 1, type(uint128).max); - - resetPrank(payer); - _approveCollector(address(tapCollector), tokens); - _depositTokens(address(tapCollector), users.indexer, tokens); - bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(tokens)); - - resetPrank(users.verifier); - _collect(IGraphPayments.PaymentTypes.QueryFee, data); - } - - function testCollect_Multiple(uint256 tokens, uint8 steps) public { - steps = uint8(bound(steps, 1, 100)); - tokens = bound(tokens, steps, type(uint128).max); - - resetPrank(payer); - _approveCollector(address(tapCollector), tokens); - _depositTokens(address(tapCollector), users.indexer, tokens); - - resetPrank(users.verifier); - uint256 payed = 0; - uint256 tokensPerStep = tokens / steps; - for (uint256 i = 0; i < steps; i++) { - bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(payed + tokensPerStep)); - _collect(IGraphPayments.PaymentTypes.QueryFee, data); - payed += tokensPerStep; - } - } - - function testCollect_RevertWhen_CallerNotDataService(uint256 tokens) public { - tokens = bound(tokens, 1, type(uint128).max); - - resetPrank(payer); - _approveCollector(address(tapCollector), tokens); - _depositTokens(address(tapCollector), users.indexer, tokens); - bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(tokens)); - - resetPrank(users.indexer); - bytes memory expectedError = abi.encodeWithSelector( - ITAPCollector.TAPCollectorCallerNotDataService.selector, - users.indexer, - users.verifier - ); - vm.expectRevert(expectedError); - tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); - } - - function testCollect_RevertWhen_InconsistentRAVTokens(uint256 tokens) public { - tokens = bound(tokens, 1, type(uint128).max); - - resetPrank(payer); - _approveCollector(address(tapCollector), tokens); - _depositTokens(address(tapCollector), users.indexer, tokens); - bytes memory data = _getQueryFeeEncodedData(users.indexer, users.verifier, uint128(tokens)); - - resetPrank(users.verifier); - _collect(IGraphPayments.PaymentTypes.QueryFee, data); - - // Attempt to collect again - vm.expectRevert(abi.encodeWithSelector( - ITAPCollector.TAPCollectorInconsistentRAVTokens.selector, - tokens, - tokens - )); - tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); - } -} diff --git a/packages/horizon/test/payments/tap-collector/TAPCollector.t.sol b/packages/horizon/test/payments/tap-collector/TAPCollector.t.sol new file mode 100644 index 000000000..25b4c901c --- /dev/null +++ b/packages/horizon/test/payments/tap-collector/TAPCollector.t.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; +import { IHorizonStakingMain } from "../../../contracts/interfaces/internal/IHorizonStakingMain.sol"; +import { ITAPCollector } from "../../../contracts/interfaces/ITAPCollector.sol"; +import { IPaymentsCollector } from "../../../contracts/interfaces/IPaymentsCollector.sol"; +import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol"; +import { TAPCollector } from "../../../contracts/payments/collectors/TAPCollector.sol"; +import { PPMMath } from "../../../contracts/libraries/PPMMath.sol"; + +import { HorizonStakingSharedTest } from "../../shared/horizon-staking/HorizonStakingShared.t.sol"; +import { PaymentsEscrowSharedTest } from "../../shared/payments-escrow/PaymentsEscrowShared.t.sol"; + +contract TAPCollectorTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest { + using PPMMath for uint256; + + address signer; + uint256 signerPrivateKey; + + /* + * MODIFIERS + */ + + modifier useSigner() { + uint256 proofDeadline = block.timestamp + 1; + bytes memory signerProof = _getSignerProof(proofDeadline, signerPrivateKey); + _authorizeSigner(signer, proofDeadline, signerProof); + _; + } + + /* + * SET UP + */ + + function setUp() public virtual override { + super.setUp(); + (signer, signerPrivateKey) = makeAddrAndKey("signer"); + vm.label({ account: signer, newLabel: "signer" }); + } + + /* + * HELPERS + */ + + function _getSignerProof(uint256 _proofDeadline, uint256 _signer) internal returns (bytes memory) { + (, address msgSender, ) = vm.readCallers(); + bytes32 messageHash = keccak256(abi.encodePacked(block.chainid, _proofDeadline, msgSender)); + bytes32 proofToDigest = MessageHashUtils.toEthSignedMessageHash(messageHash); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signer, proofToDigest); + return abi.encodePacked(r, s, v); + } + + /* + * ACTIONS + */ + + function _authorizeSigner(address _signer, uint256 _proofDeadline, bytes memory _proof) internal { + (, address msgSender, ) = vm.readCallers(); + + vm.expectEmit(address(tapCollector)); + emit ITAPCollector.SignerAuthorized(msgSender, _signer); + + tapCollector.authorizeSigner(_signer, _proofDeadline, _proof); + + (address _payer, uint256 thawEndTimestamp) = tapCollector.authorizedSigners(_signer); + assertEq(_payer, msgSender); + assertEq(thawEndTimestamp, 0); + } + + function _thawSigner(address _signer) internal { + (, address msgSender, ) = vm.readCallers(); + uint256 expectedThawEndTimestamp = block.timestamp + revokeSignerThawingPeriod; + + vm.expectEmit(address(tapCollector)); + emit ITAPCollector.SignerThawing(msgSender, _signer, expectedThawEndTimestamp); + + tapCollector.thawSigner(_signer); + + (address _payer, uint256 thawEndTimestamp) = tapCollector.authorizedSigners(_signer); + assertEq(_payer, msgSender); + assertEq(thawEndTimestamp, expectedThawEndTimestamp); + } + + function _cancelThawSigner(address _signer) internal { + (, address msgSender, ) = vm.readCallers(); + + vm.expectEmit(address(tapCollector)); + emit ITAPCollector.SignerThawCanceled(msgSender, _signer, 0); + + tapCollector.cancelThawSigner(_signer); + + (address _payer, uint256 thawEndTimestamp) = tapCollector.authorizedSigners(_signer); + assertEq(_payer, msgSender); + assertEq(thawEndTimestamp, 0); + } + + function _revokeAuthorizedSigner(address _signer) internal { + (, address msgSender, ) = vm.readCallers(); + + vm.expectEmit(address(tapCollector)); + emit ITAPCollector.SignerRevoked(msgSender, _signer); + + tapCollector.revokeAuthorizedSigner(_signer); + + (address _payer, uint256 thawEndTimestamp) = tapCollector.authorizedSigners(_signer); + assertEq(_payer, address(0)); + assertEq(thawEndTimestamp, 0); + } + + function _collect(IGraphPayments.PaymentTypes _paymentType, bytes memory _data) internal { + (ITAPCollector.SignedRAV memory signedRAV, uint256 dataServiceCut) = abi.decode(_data, (ITAPCollector.SignedRAV, uint256)); + bytes32 messageHash = tapCollector.encodeRAV(signedRAV.rav); + address _signer = ECDSA.recover(messageHash, signedRAV.signature); + (address _payer, ) = tapCollector.authorizedSigners(_signer); + uint256 tokensAlreadyCollected = tapCollector.tokensCollected(signedRAV.rav.dataService, signedRAV.rav.serviceProvider, _payer); + uint256 tokensToCollect = signedRAV.rav.valueAggregate - tokensAlreadyCollected; + uint256 tokensDataService = tokensToCollect.mulPPM(dataServiceCut); + + vm.expectEmit(address(tapCollector)); + emit IPaymentsCollector.PaymentCollected( + _paymentType, + _payer, + signedRAV.rav.serviceProvider, + tokensToCollect, + signedRAV.rav.dataService, + tokensDataService + ); + emit ITAPCollector.RAVCollected( + _payer, + signedRAV.rav.dataService, + signedRAV.rav.serviceProvider, + signedRAV.rav.timestampNs, + signedRAV.rav.valueAggregate, + signedRAV.rav.metadata, + signedRAV.signature + ); + + uint256 tokensCollected = tapCollector.collect(_paymentType, _data); + assertEq(tokensCollected, tokensToCollect); + + uint256 tokensCollectedAfter = tapCollector.tokensCollected(signedRAV.rav.dataService, signedRAV.rav.serviceProvider, _payer); + assertEq(tokensCollectedAfter, signedRAV.rav.valueAggregate); + } +} diff --git a/packages/horizon/test/payments/tap-collector/collect/collect.t.sol b/packages/horizon/test/payments/tap-collector/collect/collect.t.sol new file mode 100644 index 000000000..06b0e027a --- /dev/null +++ b/packages/horizon/test/payments/tap-collector/collect/collect.t.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ITAPCollector } from "../../../../contracts/interfaces/ITAPCollector.sol"; +import { IGraphPayments } from "../../../../contracts/interfaces/IGraphPayments.sol"; + +import { TAPCollectorTest } from "../TAPCollector.t.sol"; + +contract TAPCollectorCollectTest is TAPCollectorTest { + + /* + * HELPERS + */ + + function _getQueryFeeEncodedData( + uint256 _signerPrivateKey, + address _indexer, + address _collector, + uint128 _tokens + ) private view returns (bytes memory) { + ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(_indexer, _collector, _tokens); + bytes32 messageHash = tapCollector.encodeRAV(rav); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerPrivateKey, messageHash); + bytes memory signature = abi.encodePacked(r, s, v); + ITAPCollector.SignedRAV memory signedRAV = ITAPCollector.SignedRAV(rav, signature); + return abi.encode(signedRAV); + } + + function _getRAV( + address _indexer, + address _collector, + uint128 _tokens + ) private pure returns (ITAPCollector.ReceiptAggregateVoucher memory rav) { + return + ITAPCollector.ReceiptAggregateVoucher({ + dataService: _collector, + serviceProvider: _indexer, + timestampNs: 0, + valueAggregate: _tokens, + metadata: abi.encode("") + }); + } + + /* + * TESTS + */ + + function testTAPCollector_Collect(uint256 tokens) public useGateway useSigner { + tokens = bound(tokens, 1, type(uint128).max); + + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testTAPCollector_Collect_Multiple(uint256 tokens, uint8 steps) public useGateway useSigner { + steps = uint8(bound(steps, 1, 100)); + tokens = bound(tokens, steps, type(uint128).max); + + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + resetPrank(users.verifier); + uint256 payed = 0; + uint256 tokensPerStep = tokens / steps; + for (uint256 i = 0; i < steps; i++) { + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(payed + tokensPerStep)); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + payed += tokensPerStep; + } + } + + function testTAPCollector_Collect_RevertWhen_CallerNotDataService(uint256 tokens) public useGateway useSigner { + tokens = bound(tokens, 1, type(uint128).max); + + resetPrank(users.gateway); + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.indexer); + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorCallerNotDataService.selector, + users.indexer, + users.verifier + ); + vm.expectRevert(expectedError); + tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testTAPCollector_Collect_RevertWhen_InconsistentRAVTokens(uint256 tokens) public useGateway useSigner { + tokens = bound(tokens, 1, type(uint128).max); + + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + + // Attempt to collect again + vm.expectRevert(abi.encodeWithSelector( + ITAPCollector.TAPCollectorInconsistentRAVTokens.selector, + tokens, + tokens + )); + tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testTAPCollector_Collect_RevertWhen_SignerNotAuthorized(uint256 tokens) public useGateway { + tokens = bound(tokens, 1, type(uint128).max); + + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + vm.expectRevert(abi.encodeWithSelector(ITAPCollector.TAPCollectorInvalidRAVSigner.selector)); + tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testTAPCollector_Collect_ThawingSigner(uint256 tokens) public useGateway useSigner { + tokens = bound(tokens, 1, type(uint128).max); + + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + // Start thawing signer + _thawSigner(signer); + skip(revokeSignerThawingPeriod + 1); + + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testTAPCollector_Collect_RevertIf_SignerWasRevoked(uint256 tokens) public useGateway useSigner { + tokens = bound(tokens, 1, type(uint128).max); + + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + // Start thawing signer + _thawSigner(signer); + skip(revokeSignerThawingPeriod + 1); + _revokeAuthorizedSigner(signer); + + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + vm.expectRevert(abi.encodeWithSelector(ITAPCollector.TAPCollectorInvalidRAVSigner.selector)); + tapCollector.collect(IGraphPayments.PaymentTypes.QueryFee, data); + } + + function testTAPCollector_Collect_ThawingSignerCanceled(uint256 tokens) public useGateway useSigner { + tokens = bound(tokens, 1, type(uint128).max); + + _approveCollector(address(tapCollector), tokens); + _depositTokens(address(tapCollector), users.indexer, tokens); + + // Start thawing signer + _thawSigner(signer); + skip(revokeSignerThawingPeriod + 1); + _cancelThawSigner(signer); + + bytes memory data = _getQueryFeeEncodedData(signerPrivateKey, users.indexer, users.verifier, uint128(tokens)); + + resetPrank(users.verifier); + _collect(IGraphPayments.PaymentTypes.QueryFee, data); + } +} diff --git a/packages/horizon/test/payments/tap-collector/signer/authorizeSigner.t.sol b/packages/horizon/test/payments/tap-collector/signer/authorizeSigner.t.sol new file mode 100644 index 000000000..b337c48c7 --- /dev/null +++ b/packages/horizon/test/payments/tap-collector/signer/authorizeSigner.t.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ITAPCollector } from "../../../../contracts/interfaces/ITAPCollector.sol"; + +import { TAPCollectorTest } from "../TAPCollector.t.sol"; + +contract TAPCollectorAuthorizeSignerTest is TAPCollectorTest { + + uint256 constant SECP256K1_CURVE_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; + + /* + * TESTS + */ + + function testTAPCollector_AuthorizeSigner(uint256 signerKey) public useGateway { + signerKey = bound(signerKey, 1, SECP256K1_CURVE_ORDER - 1); + uint256 proofDeadline = block.timestamp + 1; + bytes memory signerProof = _getSignerProof(proofDeadline, signerKey); + _authorizeSigner(vm.addr(signerKey), proofDeadline, signerProof); + } + + function testTAPCollector_AuthorizeSigner_RevertWhen_Invalid() public useGateway { + // Sign proof with payer + uint256 proofDeadline = block.timestamp + 1; + bytes memory signerProof = _getSignerProof(proofDeadline, signerPrivateKey); + + // Attempt to authorize delegator with payer's proof + bytes memory expectedError = abi.encodeWithSelector(ITAPCollector.TAPCollectorInvalidSignerProof.selector); + vm.expectRevert(expectedError); + tapCollector.authorizeSigner(users.delegator, proofDeadline, signerProof); + } + + function testTAPCollector_AuthorizeSigner_RevertWhen_AlreadyAuthroized() public useGateway { + // Authorize signer + uint256 proofDeadline = block.timestamp + 1; + bytes memory signerProof = _getSignerProof(proofDeadline, signerPrivateKey); + _authorizeSigner(signer, proofDeadline, signerProof); + + // Attempt to authorize signer again + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorSignerAlreadyAuthorized.selector, + users.gateway, + signer + ); + vm.expectRevert(expectedError); + tapCollector.authorizeSigner(signer, proofDeadline, signerProof); + } + + function testTAPCollector_AuthorizeSigner_RevertWhen_ProofExpired() public useGateway { + // Sign proof with payer + uint256 proofDeadline = block.timestamp - 1; + bytes memory signerProof = _getSignerProof(proofDeadline, signerPrivateKey); + + // Attempt to authorize delegator with expired proof + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorInvalidSignerProofDeadline.selector, + proofDeadline, + block.timestamp + ); + vm.expectRevert(expectedError); + tapCollector.authorizeSigner(users.delegator, proofDeadline, signerProof); + } +} diff --git a/packages/horizon/test/payments/tap-collector/signer/cancelThawSigner.t.sol b/packages/horizon/test/payments/tap-collector/signer/cancelThawSigner.t.sol new file mode 100644 index 000000000..dc25da8cf --- /dev/null +++ b/packages/horizon/test/payments/tap-collector/signer/cancelThawSigner.t.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ITAPCollector } from "../../../../contracts/interfaces/ITAPCollector.sol"; + +import { TAPCollectorTest } from "../TAPCollector.t.sol"; + +contract TAPCollectorCancelThawSignerTest is TAPCollectorTest { + + /* + * TESTS + */ + + function testTAPCollector_CancelThawSigner() public useGateway useSigner { + _thawSigner(signer); + _cancelThawSigner(signer); + } + + function testTAPCollector_CancelThawSigner_RevertWhen_NotAuthorized() public useGateway { + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorSignerNotAuthorizedByPayer.selector, + users.gateway, + signer + ); + vm.expectRevert(expectedError); + tapCollector.thawSigner(signer); + } + + function testTAPCollector_CancelThawSigner_RevertWhen_NotThawing() public useGateway useSigner { + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorSignerNotThawing.selector, + signer + ); + vm.expectRevert(expectedError); + tapCollector.cancelThawSigner(signer); + } +} diff --git a/packages/horizon/test/payments/tap-collector/signer/revokeSigner.t.sol b/packages/horizon/test/payments/tap-collector/signer/revokeSigner.t.sol new file mode 100644 index 000000000..8c03245f8 --- /dev/null +++ b/packages/horizon/test/payments/tap-collector/signer/revokeSigner.t.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ITAPCollector } from "../../../../contracts/interfaces/ITAPCollector.sol"; + +import { TAPCollectorTest } from "../TAPCollector.t.sol"; + +contract TAPCollectorRevokeAuthorizedSignerTest is TAPCollectorTest { + + /* + * TESTS + */ + + function testTAPCollector_RevokeAuthorizedSigner() public useGateway useSigner { + _thawSigner(signer); + + // Advance time to thaw signer + skip(revokeSignerThawingPeriod + 1); + + _revokeAuthorizedSigner(signer); + } + + function testTAPCollector_RevokeAuthorizedSigner_RevertWhen_NotAuthorized() public useGateway { + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorSignerNotAuthorizedByPayer.selector, + users.gateway, + signer + ); + vm.expectRevert(expectedError); + tapCollector.revokeAuthorizedSigner(signer); + } + + function testTAPCollector_RevokeAuthorizedSigner_RevertWhen_NotThawing() public useGateway useSigner { + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorSignerNotThawing.selector, + signer + ); + vm.expectRevert(expectedError); + tapCollector.revokeAuthorizedSigner(signer); + } + + function testTAPCollector_RevokeAuthorizedSigner_RevertWhen_StillThawing() public useGateway useSigner { + _thawSigner(signer); + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorSignerStillThawing.selector, + block.timestamp, + block.timestamp + revokeSignerThawingPeriod + ); + vm.expectRevert(expectedError); + tapCollector.revokeAuthorizedSigner(signer); + } +} diff --git a/packages/horizon/test/payments/tap-collector/signer/thawSigner.t.sol b/packages/horizon/test/payments/tap-collector/signer/thawSigner.t.sol new file mode 100644 index 000000000..fb47c37fb --- /dev/null +++ b/packages/horizon/test/payments/tap-collector/signer/thawSigner.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import "forge-std/Test.sol"; + +import { ITAPCollector } from "../../../../contracts/interfaces/ITAPCollector.sol"; + +import { TAPCollectorTest } from "../TAPCollector.t.sol"; + +contract TAPCollectorThawSignerTest is TAPCollectorTest { + + /* + * TESTS + */ + + function testTAPCollector_ThawSigner() public useGateway useSigner { + _thawSigner(signer); + } + + function testTAPCollector_ThawSigner_RevertWhen_NotAuthorized() public useGateway { + bytes memory expectedError = abi.encodeWithSelector( + ITAPCollector.TAPCollectorSignerNotAuthorizedByPayer.selector, + users.gateway, + signer + ); + vm.expectRevert(expectedError); + tapCollector.thawSigner(signer); + } +} diff --git a/packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol b/packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol index b7ee76839..2bc435f7a 100644 --- a/packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol +++ b/packages/horizon/test/shared/payments-escrow/PaymentsEscrowShared.t.sol @@ -8,6 +8,16 @@ import { GraphBaseTest } from "../../GraphBase.t.sol"; abstract contract PaymentsEscrowSharedTest is GraphBaseTest { + /* + * MODIFIERS + */ + + modifier useGateway() { + vm.startPrank(users.gateway); + _; + vm.stopPrank(); + } + /* * HELPERS */ diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index 5b1449ea7..cd5cc2bfb 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -18,4 +18,6 @@ abstract contract Constants { uint256 internal constant EPOCH_LENGTH = 1; // Rewards manager uint256 internal constant ALLOCATIONS_REWARD_CUT = 100 ether; + // TAPCollector + uint256 internal constant revokeSignerThawingPeriod = 7 days; } \ No newline at end of file diff --git a/packages/subgraph-service/test/SubgraphBaseTest.t.sol b/packages/subgraph-service/test/SubgraphBaseTest.t.sol index 43065add6..099164473 100644 --- a/packages/subgraph-service/test/SubgraphBaseTest.t.sol +++ b/packages/subgraph-service/test/SubgraphBaseTest.t.sol @@ -147,7 +147,7 @@ abstract contract SubgraphBaseTest is Utils, Constants { disputeManager = DisputeManager(disputeManagerProxy); disputeManager.transferOwnership(users.governor); - tapCollector = new TAPCollector("TAPCollector", "1", address(controller)); + tapCollector = new TAPCollector("TAPCollector", "1", address(controller), revokeSignerThawingPeriod); address subgraphServiceImplementation = address( new SubgraphService(address(controller), address(disputeManager), address(tapCollector), address(curation)) ); diff --git a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol index 013f869a8..b417f30bf 100644 --- a/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol +++ b/packages/subgraph-service/test/subgraphService/SubgraphService.t.sol @@ -232,7 +232,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest { ITAPCollector.SignedRAV memory signedRav = abi.decode(_data, (ITAPCollector.SignedRAV)); allocationId = abi.decode(signedRav.rav.metadata, (address)); allocation = subgraphService.getAllocation(allocationId); - address payer = _recoverRAVSigner(signedRav); + (address payer, ) = tapCollector.authorizedSigners(_recoverRAVSigner(signedRav)); // Total amount of tokens collected for indexer uint256 tokensCollected = tapCollector.tokensCollected(address(subgraphService), _indexer, payer); diff --git a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol index 99bfab1ca..93972679f 100644 --- a/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol +++ b/packages/subgraph-service/test/subgraphService/collect/query/query.t.sol @@ -3,11 +3,11 @@ pragma solidity 0.8.27; import "forge-std/Test.sol"; -// import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol"; import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol"; import { ITAPCollector } from "@graphprotocol/horizon/contracts/interfaces/ITAPCollector.sol"; import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol"; import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol"; +import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import { ISubgraphService } from "../../../../contracts/interfaces/ISubgraphService.sol"; import { SubgraphServiceTest } from "../../SubgraphService.t.sol"; @@ -23,6 +23,14 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { * HELPERS */ + function _getSignerProof(uint256 _proofDeadline, uint256 _signer) private returns (bytes memory) { + (, address msgSender, ) = vm.readCallers(); + bytes32 messageHash = keccak256(abi.encodePacked(block.chainid, _proofDeadline, msgSender)); + bytes32 proofToDigest = MessageHashUtils.toEthSignedMessageHash(messageHash); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signer, proofToDigest); + return abi.encodePacked(r, s, v); + } + function _getQueryFeeEncodedData(address indexer, uint128 tokens) private view returns (bytes memory) { ITAPCollector.ReceiptAggregateVoucher memory rav = _getRAV(indexer, tokens); bytes32 messageHash = tapCollector.encodeRAV(rav); @@ -47,14 +55,15 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { } function _approveCollector(uint256 tokens) private { - address msgSender; - (, msgSender, ) = vm.readCallers(); - resetPrank(signer); - mint(signer, tokens); escrow.approveCollector(address(tapCollector), tokens); token.approve(address(escrow), tokens); escrow.deposit(address(tapCollector), users.indexer, tokens); - resetPrank(msgSender); + } + + function _authorizeSigner() private { + uint256 proofDeadline = block.timestamp + 1; + bytes memory proof = _getSignerProof(proofDeadline, signerPrivateKey); + tapCollector.authorizeSigner(signer, proofDeadline, proof); } /* @@ -81,22 +90,28 @@ contract SubgraphServiceRegisterTest is SubgraphServiceTest { : tokensAllocated / stakeToFeesRatio; tokensPayment = bound(tokensPayment, minimumProvisionTokens, maxTokensPayment); + resetPrank(users.gateway); _approveCollector(tokensPayment); + _authorizeSigner(); + resetPrank(users.indexer); bytes memory data = _getQueryFeeEncodedData(users.indexer, uint128(tokensPayment)); _collect(users.indexer, IGraphPayments.PaymentTypes.QueryFee, data); } function testCollect_MultipleQueryFees( uint256 tokensAllocated, - uint256 numPayments + uint8 numPayments ) public useIndexer useAllocation(tokensAllocated) { vm.assume(tokensAllocated > minimumProvisionTokens * stakeToFeesRatio); - numPayments = bound(numPayments, 1, 10); + numPayments = uint8(bound(numPayments, 2, 10)); uint256 tokensPayment = tokensAllocated / stakeToFeesRatio / numPayments; + resetPrank(users.gateway); _approveCollector(tokensAllocated); + _authorizeSigner(); + resetPrank(users.indexer); uint256 accTokensPayment = 0; for (uint i = 0; i < numPayments; i++) { accTokensPayment = accTokensPayment + tokensPayment; diff --git a/packages/subgraph-service/test/utils/Constants.sol b/packages/subgraph-service/test/utils/Constants.sol index f1aac3d16..76f864da1 100644 --- a/packages/subgraph-service/test/utils/Constants.sol +++ b/packages/subgraph-service/test/utils/Constants.sol @@ -27,4 +27,6 @@ abstract contract Constants { // RewardsMananger parameters uint256 public constant rewardsPerSignal = 10000; uint256 public constant rewardsPerSubgraphAllocationUpdate = 1000; + // TAPCollector parameters + uint256 public constant revokeSignerThawingPeriod = 7 days; } From 0c0d09090f6f8cff63a7cb4d499d94f579d159ba Mon Sep 17 00:00:00 2001 From: Miguel de Elias Date: Thu, 10 Oct 2024 22:42:29 -0300 Subject: [PATCH 277/277] fix: lint errors --- .../libraries/ProvisionTracker.sol | 28 +++++++++---------- .../contracts/staking/HorizonStaking.sol | 4 +-- .../contracts/staking/HorizonStakingBase.sol | 16 +++++------ .../contracts/utilities/AllocationManager.sol | 28 +++++++++---------- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol index fef392302..25449909b 100644 --- a/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol +++ b/packages/horizon/contracts/data-service/libraries/ProvisionTracker.sol @@ -42,6 +42,20 @@ library ProvisionTracker { self[serviceProvider] += tokens; } + /** + * @notice Releases tokens for a service provider + * @dev Requirements: + * - `tokens` must be less than or equal to the amount of tokens locked for the service provider + * @param self The provision tracker mapping + * @param serviceProvider The service provider address + * @param tokens The amount of tokens to release + */ + function release(mapping(address => uint256) storage self, address serviceProvider, uint256 tokens) internal { + if (tokens == 0) return; + require(self[serviceProvider] >= tokens, ProvisionTrackerInsufficientTokens(self[serviceProvider], tokens)); + self[serviceProvider] -= tokens; + } + /** * @notice Checks if a service provider has enough tokens available to lock * @param self The provision tracker mapping @@ -58,18 +72,4 @@ library ProvisionTracker { uint256 tokensAvailable = graphStaking.getTokensAvailable(serviceProvider, address(this), delegationRatio); return self[serviceProvider] <= tokensAvailable; } - - /** - * @notice Releases tokens for a service provider - * @dev Requirements: - * - `tokens` must be less than or equal to the amount of tokens locked for the service provider - * @param self The provision tracker mapping - * @param serviceProvider The service provider address - * @param tokens The amount of tokens to release - */ - function release(mapping(address => uint256) storage self, address serviceProvider, uint256 tokens) internal { - if (tokens == 0) return; - require(self[serviceProvider] >= tokens, ProvisionTrackerInsufficientTokens(self[serviceProvider], tokens)); - self[serviceProvider] -= tokens; - } } diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index c46670dcb..8df8f20f6 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -836,7 +836,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { address _serviceProvider, address _verifier, uint256 _shares, - address beneficiary + address _beneficiary ) private returns (bytes32) { require(_shares > 0, HorizonStakingInvalidZeroShares()); DelegationPoolInternal storage pool = _getDelegationPool(_serviceProvider, _verifier); @@ -862,7 +862,7 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain { bytes32 thawRequestId = _createThawRequest( _serviceProvider, _verifier, - beneficiary, + _beneficiary, thawingShares, thawingUntil, pool.thawingNonce diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 54e55e1cc..d29d3edec 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -288,14 +288,6 @@ abstract contract HorizonStakingBase is return _provisions[_serviceProvider][_verifier].tokens - _provisions[_serviceProvider][_verifier].tokensThawing; } - /** - * @notice See {IHorizonStakingBase-getDelegatedTokensAvailable}. - */ - function _getDelegatedTokensAvailable(address _serviceProvider, address _verifier) private view returns (uint256) { - DelegationPoolInternal storage poolInternal = _getDelegationPool(_serviceProvider, _verifier); - return poolInternal.tokens - poolInternal.tokensThawing; - } - /** * @notice Gets the next thaw request after `_thawRequestId`. * @dev This function is used as a callback in the thaw requests linked list traversal. @@ -303,4 +295,12 @@ abstract contract HorizonStakingBase is function _getNextThawRequest(bytes32 _thawRequestId) internal view returns (bytes32) { return _thawRequests[_thawRequestId].next; } + + /** + * @notice See {IHorizonStakingBase-getDelegatedTokensAvailable}. + */ + function _getDelegatedTokensAvailable(address _serviceProvider, address _verifier) private view returns (uint256) { + DelegationPoolInternal storage poolInternal = _getDelegationPool(_serviceProvider, _verifier); + return poolInternal.tokens - poolInternal.tokensThawing; + } } diff --git a/packages/subgraph-service/contracts/utilities/AllocationManager.sol b/packages/subgraph-service/contracts/utilities/AllocationManager.sol index 5da237ee6..669cd9bf8 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManager.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManager.sol @@ -457,20 +457,6 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca return legacyAllocations.get(_allocationId); } - /** - * @notice Verifies ownership of an allocation id by verifying an EIP712 allocation proof - * @dev Requirements: - * - Signer must be the allocation id address - * @param _indexer The address of the indexer - * @param _allocationId The id of the allocation - * @param _proof The EIP712 proof, an EIP712 signed message of (indexer,allocationId) - */ - function _verifyAllocationProof(address _indexer, address _allocationId, bytes memory _proof) private view { - bytes32 digest = _encodeAllocationProof(_indexer, _allocationId); - address signer = ECDSA.recover(digest, _proof); - require(signer == _allocationId, AllocationManagerInvalidAllocationProof(signer, _allocationId)); - } - /** * @notice Encodes the allocation proof for EIP712 signing * @param _indexer The address of the indexer @@ -489,4 +475,18 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca function _isOverAllocated(address _indexer, uint32 _delegationRatio) internal view returns (bool) { return !allocationProvisionTracker.check(_graphStaking(), _indexer, _delegationRatio); } + + /** + * @notice Verifies ownership of an allocation id by verifying an EIP712 allocation proof + * @dev Requirements: + * - Signer must be the allocation id address + * @param _indexer The address of the indexer + * @param _allocationId The id of the allocation + * @param _proof The EIP712 proof, an EIP712 signed message of (indexer,allocationId) + */ + function _verifyAllocationProof(address _indexer, address _allocationId, bytes memory _proof) private view { + bytes32 digest = _encodeAllocationProof(_indexer, _allocationId); + address signer = ECDSA.recover(digest, _proof); + require(signer == _allocationId, AllocationManagerInvalidAllocationProof(signer, _allocationId)); + } }