Skip to content

Commit

Permalink
chore: add horizon unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Maikol committed May 25, 2024
1 parent 180513e commit e7c00c1
Show file tree
Hide file tree
Showing 19 changed files with 971 additions and 16 deletions.
12 changes: 9 additions & 3 deletions packages/horizon/test/GraphBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/horizon/test/escrow/GraphEscrow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
8 changes: 5 additions & 3 deletions packages/horizon/test/escrow/collect.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ 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);

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);
Expand Down
8 changes: 6 additions & 2 deletions packages/horizon/test/payments/GraphPayments.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
_;
}

Expand All @@ -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);
}
}
86 changes: 86 additions & 0 deletions packages/horizon/test/staking/HorizonStaking.t.sol
Original file line number Diff line number Diff line change
@@ -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);
}
}
42 changes: 42 additions & 0 deletions packages/horizon/test/staking/delegation/delegate.t.sol
Original file line number Diff line number Diff line change
@@ -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);
}
}
76 changes: 76 additions & 0 deletions packages/horizon/test/staking/delegation/undelegate.t.sol
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading

0 comments on commit e7c00c1

Please sign in to comment.