Skip to content

Commit

Permalink
test: add data service framework tests
Browse files Browse the repository at this point in the history
Signed-off-by: Tomás Migone <[email protected]>
  • Loading branch information
tmigone committed Jun 11, 2024
1 parent aba7ac5 commit df297f7
Show file tree
Hide file tree
Showing 11 changed files with 589 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
400 changes: 382 additions & 18 deletions packages/horizon/test/data-service/DataService.t.sol

Large diffs are not rendered by default.

72 changes: 70 additions & 2 deletions packages/horizon/test/data-service/DataService.tree
Original file line number Diff line number Diff line change
@@ -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
└── 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
18 changes: 0 additions & 18 deletions packages/horizon/test/data-service/DataServiceBase.sol

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DataServiceUpgradeableTest
└── when the contract is deployed with a valid controller
└── it should set all it's ranges to max
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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);
Expand All @@ -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));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { GraphBaseTest } from "../../GraphBase.t.sol";
import { IGraphPayments } from "../../../contracts/interfaces/IGraphPayments.sol";

abstract contract HorizonStakingSharedTest is GraphBaseTest {

/*
* MODIFIERS
*/
Expand All @@ -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);
_;
}

Expand All @@ -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,
Expand All @@ -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 {
Expand Down

0 comments on commit df297f7

Please sign in to comment.