@@ -171,7 +171,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
171
171
* @dev Check if the caller is the slasher.
172
172
*/
173
173
modifier onlySlasher {
174
- require (slashers[msg .sender ] == true , "Caller is not a Slasher " );
174
+ require (slashers[msg .sender ] == true , "!slasher " );
175
175
_;
176
176
}
177
177
@@ -194,6 +194,10 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
194
194
*/
195
195
function initialize (address _controller ) external onlyImpl {
196
196
Managed._initialize (_controller);
197
+
198
+ // By default 100% rebate ratio to fees
199
+ alphaNumerator = 1 ;
200
+ alphaDenominator = 1 ;
197
201
}
198
202
199
203
/**
@@ -258,6 +262,22 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
258
262
emit ParameterUpdated ("maxAllocationEpochs " );
259
263
}
260
264
265
+ /**
266
+ * @dev Set the rebate ratio (fees to allocated stake).
267
+ * @param _alphaNumerator Numerator of `alpha` in the cobb-douglas function
268
+ * @param _alphaDenominator Denominator of `alpha` in the cobb-douglas function
269
+ */
270
+ function setRebateRatio (uint32 _alphaNumerator , uint32 _alphaDenominator )
271
+ external
272
+ override
273
+ onlyGovernor
274
+ {
275
+ require (_alphaNumerator > 0 && _alphaDenominator > 0 , "=zero " );
276
+ alphaNumerator = _alphaNumerator;
277
+ alphaDenominator = _alphaDenominator;
278
+ emit ParameterUpdated ("rebateRatio " );
279
+ }
280
+
261
281
/**
262
282
* @dev Set the delegation capacity multiplier.
263
283
* @param _delegationCapacity Delegation capacity multiplier
@@ -565,7 +585,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
565
585
566
586
// Cannot slash stake of an indexer without any or enough stake
567
587
require (indexerStake.hasTokens (), "Indexer has no stakes " );
568
- require (_tokens <= indexerStake.tokensStaked, "cannot slash more than staked amount " );
588
+ require (_tokens <= indexerStake.tokensStaked, "Cannot slash more than staked amount " );
569
589
570
590
// Validate beneficiary of slashed tokens
571
591
require (_beneficiary != address (0 ), "Beneficiary must not be an empty address " );
@@ -583,11 +603,10 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
583
603
// Remove tokens to slash from the stake
584
604
indexerStake.release (_tokens);
585
605
606
+ // -- Effects --
607
+
586
608
// Set apart the reward for the beneficiary and burn remaining slashed stake
587
- uint256 tokensToBurn = _tokens.sub (_reward);
588
- if (tokensToBurn > 0 ) {
589
- graphToken ().burn (tokensToBurn);
590
- }
609
+ _burnTokens (_tokens.sub (_reward));
591
610
592
611
// Give the beneficiary a reward for slashing
593
612
if (_reward > 0 ) {
@@ -759,7 +778,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
759
778
}
760
779
761
780
/**
762
- * @dev Collect query fees for an allocation.
781
+ * @dev Collect query fees for an allocation from state channels .
763
782
* Funds received are only accepted from a valid source.
764
783
* @param _tokens Amount of tokens to collect
765
784
*/
@@ -795,23 +814,16 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
795
814
AllocationState allocState = _getAllocationState (_allocationID);
796
815
797
816
// Validate ownership
798
- require (_onlyAuthOrDelegator (alloc.indexer), "Caller must be authorized " );
817
+ require (_onlyAuthOrDelegator (alloc.indexer), "!auth " );
799
818
800
819
// TODO: restake when delegator called should not be allowed?
801
820
802
821
// Funds can only be claimed after a period of time passed since allocation was closed
803
822
require (allocState == AllocationState.Finalized, "Allocation must be in finalized state " );
804
823
805
- // Find a rebate pool for the epoch
806
- Rebates.Pool storage pool = rebates[alloc.closedAtEpoch];
807
-
808
- // Process rebate
809
- uint256 tokensToClaim = pool.redeem (alloc.collectedFees, alloc.effectiveAllocation);
810
-
811
- // When all allocations processed then prune rebate pool
812
- if (pool.unclaimedAllocationsCount == 0 ) {
813
- delete rebates[alloc.closedAtEpoch];
814
- }
824
+ // Process rebate reward
825
+ Rebates.Pool storage rebatePool = rebates[alloc.closedAtEpoch];
826
+ uint256 tokensToClaim = rebatePool.redeem (alloc.collectedFees, alloc.effectiveAllocation);
815
827
816
828
// Calculate delegation rewards and add them to the delegation pool
817
829
uint256 delegationRewards = _collectDelegationQueryRewards (alloc.indexer, tokensToClaim);
@@ -828,6 +840,14 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
828
840
alloc.effectiveAllocation = 0 ;
829
841
alloc.assetHolder = address (0 ); // This avoid collect() to be called
830
842
843
+ // -- Effects --
844
+
845
+ // When all allocations processed then burn unclaimed fees and prune rebate pool
846
+ if (rebatePool.unclaimedAllocationsCount == 0 ) {
847
+ _burnTokens (rebatePool.unclaimedFees ());
848
+ delete rebates[closedAtEpoch];
849
+ }
850
+
831
851
// When there are tokens to claim from the rebate pool, transfer or restake
832
852
if (tokensToClaim > 0 ) {
833
853
// Assign claimed tokens
@@ -850,7 +870,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
850
870
epochManager ().currentEpoch (),
851
871
closedAtEpoch,
852
872
tokensToClaim,
853
- pool .unclaimedAllocationsCount,
873
+ rebatePool .unclaimedAllocationsCount,
854
874
delegationRewards
855
875
);
856
876
}
@@ -893,7 +913,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
893
913
address _assetHolder ,
894
914
bytes32 _metadata
895
915
) internal {
896
- require (_onlyAuth (_indexer), "Caller must be authorized " );
916
+ require (_onlyAuth (_indexer), "!auth " );
897
917
898
918
Stakes.Indexer storage indexerStake = stakes[_indexer];
899
919
@@ -982,20 +1002,23 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
982
1002
983
1003
// Validate ownership
984
1004
if (epochs > maxAllocationEpochs) {
985
- // Verify that the allocation owner or delegator is settling
986
- require (_onlyAuthOrDelegator (alloc.indexer), "Caller must be authorized " );
1005
+ // Verify that the allocation owner or delegator is closing
1006
+ require (_onlyAuthOrDelegator (alloc.indexer), "!auth " );
987
1007
} else {
988
- // Verify that the allocation owner is settling
989
- require (_onlyAuth (alloc.indexer), "Caller must be authorized " );
1008
+ // Verify that the allocation owner is closing
1009
+ require (_onlyAuth (alloc.indexer), "!auth " );
990
1010
}
991
1011
992
- // Close the allocation and start counting a period to finalize any other
993
- // withdrawal .
1012
+ // Close the allocation and start counting a period to settle remaining payments from
1013
+ // state channels .
994
1014
alloc.closedAtEpoch = currentEpoch;
995
1015
alloc.effectiveAllocation = _getEffectiveAllocation (alloc.tokens, epochs);
996
1016
997
- // Send funds to rebate pool and account the effective allocation
1017
+ // Account collected fees and effective allocation in rebate pool for the epoch
998
1018
Rebates.Pool storage rebatePool = rebates[currentEpoch];
1019
+ if (! rebatePool.exists ()) {
1020
+ rebatePool.init (alphaNumerator, alphaDenominator);
1021
+ }
999
1022
rebatePool.addToPool (alloc.collectedFees, alloc.effectiveAllocation);
1000
1023
1001
1024
// Distribute rewards if proof of indexing was presented
@@ -1025,17 +1048,17 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1025
1048
}
1026
1049
1027
1050
/**
1028
- * @dev Withdraw and collect funds for an allocation.
1029
- * @param _allocationID Allocation that is receiving collected funds
1051
+ * @dev Collect query fees for an allocation from the state channel .
1052
+ * @param _allocationID Allocation that is receiving query fees
1030
1053
* @param _from Source of collected funds for the allocation
1031
- * @param _tokens Amount of tokens to withdraw
1054
+ * @param _tokens Amount of tokens to collect
1032
1055
*/
1033
1056
function _collect (
1034
1057
address _allocationID ,
1035
1058
address _from ,
1036
1059
uint256 _tokens
1037
1060
) internal {
1038
- uint256 rebateFees = _tokens;
1061
+ uint256 queryFees = _tokens;
1039
1062
1040
1063
// Get allocation
1041
1064
Allocation storage alloc = allocations[_allocationID];
@@ -1047,26 +1070,29 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1047
1070
"Allocation must be active or closed "
1048
1071
);
1049
1072
1050
- // Collect protocol fees to be burned
1051
- uint256 protocolFees = _collectProtocolFees (rebateFees );
1052
- rebateFees = rebateFees .sub (protocolFees);
1073
+ // Calculate protocol fees to be burned
1074
+ uint256 protocolFees = _collectProtocolFees (queryFees );
1075
+ queryFees = queryFees .sub (protocolFees);
1053
1076
1054
- // Calculate curation fees only if the subgraph deployment is curated
1055
- uint256 curationFees = _collectCurationFees (alloc.subgraphDeploymentID, rebateFees );
1056
- rebateFees = rebateFees .sub (curationFees);
1077
+ // Calculate curation fees ( only if the subgraph deployment is curated)
1078
+ uint256 curationFees = _collectCurationFees (alloc.subgraphDeploymentID, queryFees );
1079
+ queryFees = queryFees .sub (curationFees);
1057
1080
1058
- // Collect funds for the allocation
1059
- alloc.collectedFees = alloc.collectedFees.add (rebateFees );
1081
+ // Collect funds on the allocation
1082
+ alloc.collectedFees = alloc.collectedFees.add (queryFees );
1060
1083
1061
1084
// When allocation is closed redirect funds to the rebate pool
1062
1085
// This way we can keep collecting tokens even after the allocation is closed and
1063
1086
// before it gets to the finalized state.
1064
1087
if (allocState == AllocationState.Closed) {
1065
1088
Rebates.Pool storage rebatePool = rebates[alloc.closedAtEpoch];
1066
- rebatePool.fees = rebatePool.fees.add (rebateFees );
1089
+ rebatePool.fees = rebatePool.fees.add (queryFees );
1067
1090
}
1068
1091
1069
- // TODO: for consistency we could burn protocol fees here
1092
+ // -- Effects --
1093
+
1094
+ // Burn protocol fees
1095
+ _burnTokens (protocolFees);
1070
1096
1071
1097
// Send curation fees to the curator reserve pool
1072
1098
if (curationFees > 0 ) {
@@ -1085,7 +1111,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1085
1111
_allocationID,
1086
1112
_from,
1087
1113
curationFees,
1088
- rebateFees
1114
+ queryFees
1089
1115
);
1090
1116
}
1091
1117
@@ -1240,11 +1266,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1240
1266
if (protocolPercentage == 0 ) {
1241
1267
return 0 ;
1242
1268
}
1243
- uint256 protocolFees = uint256 (protocolPercentage).mul (_tokens).div (MAX_PPM);
1244
- if (protocolFees > 0 ) {
1245
- graphToken ().burn (protocolFees);
1246
- }
1247
- return protocolFees;
1269
+ return uint256 (protocolPercentage).mul (_tokens).div (MAX_PPM);
1248
1270
}
1249
1271
1250
1272
/**
@@ -1362,4 +1384,14 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1362
1384
1363
1385
return totalRewards;
1364
1386
}
1387
+
1388
+ /**
1389
+ * @dev Burn tokens held by this contract.
1390
+ * @param _amount Amount of tokens to burn
1391
+ */
1392
+ function _burnTokens (uint256 _amount ) internal {
1393
+ if (_amount > 0 ) {
1394
+ graphToken ().burn (_amount);
1395
+ }
1396
+ }
1365
1397
}
0 commit comments