Skip to content

Commit 5216c17

Browse files
committed
Implement tests for subgraph owner fee
1 parent 19516ea commit 5216c17

File tree

4 files changed

+52
-46
lines changed

4 files changed

+52
-46
lines changed

cli/commands/protocol/get.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const gettersList = {
4141
// GNS
4242
'gns-minimum-signal': { contract: 'GNS', name: 'minimumVSignalStake' },
4343
'gns-bonding-curve': { contract: 'GNS', name: 'bondingCurve' },
44-
'gns-deprecate-fee-percentage': { contract: 'GNS', name: 'changeFeePercentage' },
44+
'gns-owner-fee-percentage': { contract: 'GNS', name: 'ownerFeePercentage' },
4545
// Token
4646
'token-governor': { contract: 'GraphToken', name: 'governor' },
4747
'token-supply': { contract: 'GraphToken', name: 'totalSupply' },

cli/commands/protocol/set.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const settersList = {
4343
'rewards-issuance-rate': { contract: 'RewardsManager', name: 'setIssuanceRate' },
4444
// GNS
4545
'gns-minimum-signal': { contract: 'GNS', name: 'setMinimumVsignal' },
46-
'gns-deprecate-fee-percentage': { contract: 'GNS', name: 'setChangeFeePercentage' },
46+
'gns-owner-fee-percentage': { contract: 'GNS', name: 'setOwnerFeePercentage' },
4747
// Token
4848
'token-transfer-governor': { contract: 'GraphToken', name: 'transferOwnership' },
4949
'token-accept-governor': { contract: 'GraphToken', name: 'acceptOwnership' },

contracts/discovery/GNS.sol

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ contract GNS is Managed {
3434
uint32 private constant defaultReserveRatio = 1000000;
3535

3636
// In parts per hundred
37-
uint32 public changeFeePercentage = 50;
37+
uint32 public ownerFeePercentage = 50;
3838

3939
// Bonding curve formula
4040
address public bondingCurve;
@@ -207,14 +207,14 @@ contract GNS is Managed {
207207
}
208208

209209
/**
210-
* @dev Set the change fee percentage. This is used to prevent a subgraph owner to drain all
210+
* @dev Set the owner fee percentage. This is used to prevent a subgraph owner to drain all
211211
* the name curators tokens while upgrading or deprecating and is configurable in parts per hundred.
212-
* @param _changeFeePercentage Change fee percentage
212+
* @param _ownerFeePercentage Owner fee percentage
213213
*/
214-
function setChangeFeePercentage(uint32 _changeFeePercentage) external onlyGovernor {
215-
require(_changeFeePercentage <= 100, "Change fee must be 100 or less");
216-
changeFeePercentage = _changeFeePercentage;
217-
emit ParameterUpdated("changeFeePercentage");
214+
function setOwnerFeePercentage(uint32 _ownerFeePercentage) external onlyGovernor {
215+
require(_ownerFeePercentage <= 100, "Owner fee must be 100 or less");
216+
ownerFeePercentage = _ownerFeePercentage;
217+
emit ParameterUpdated("ownerFeePercentage");
218218
}
219219

220220
/**
@@ -388,12 +388,11 @@ contract GNS is Managed {
388388
require(namePool.disabled == false, "GNS: Cannot be disabled");
389389

390390
uint256 vSignalOld = nSignalToVSignal(_graphAccount, _subgraphNumber, namePool.nSignal);
391-
(uint256 tokens, uint256 withdrawalFees) = _burnVSignal(
391+
(uint256 tokens, , uint256 ownerFee) = _burnVSignal(
392392
_graphAccount,
393393
namePool.subgraphDeploymentID,
394394
vSignalOld
395395
);
396-
uint256 ownerFee = _ownerFee(withdrawalFees, _graphAccount);
397396
namePool.vSignal = namePool.vSignal.sub(vSignalOld);
398397
// Update name signals deployment ID to match the subgraphs deployment ID
399398
namePool.subgraphDeploymentID = _newSubgraphDeploymentID;
@@ -405,7 +404,7 @@ contract GNS is Managed {
405404
_graphAccount,
406405
_subgraphNumber,
407406
vSignalNew,
408-
tokens + withdrawalFees,
407+
tokens + ownerFee,
409408
_newSubgraphDeploymentID
410409
);
411410
}
@@ -470,12 +469,11 @@ contract GNS is Managed {
470469
namePool.vSignal = 0;
471470
// If no nSignal, then no need to burn vSignal
472471
if (namePool.nSignal != 0) {
473-
(uint256 tokens, uint256 withdrawalFees) = curation().burn(
474-
_subgraphDeploymentID,
472+
(uint256 tokens, , uint256 ownerFee) = _burnVSignal(
473+
_graphAccount,
474+
namePool.subgraphDeploymentID,
475475
vSignal
476476
);
477-
478-
uint256 ownerFee = _ownerFee(withdrawalFees, _graphAccount);
479477
namePool.withdrawableGRT = tokens + ownerFee;
480478
}
481479
// Set the NameCurationPool fields to make it disabled
@@ -566,19 +564,24 @@ contract GNS is Managed {
566564
* @param _graphAccount Subgraph owner
567565
* @param _subgraphDeploymentID Subgraph deployment to burn all vSignal from
568566
* @param _vSignal vSignal being burnt
569-
* @return Tokens returned to the gns contract, and withdrawal fees the owner transferred to the gns
567+
* @return Tokens returned to the gns contract, withdrawal fees charged, and the owner fee
568+
* that the owner reimbursed from the withdrawal fee
570569
*/
571570
function _burnVSignal(
572571
address _graphAccount,
573572
bytes32 _subgraphDeploymentID,
574573
uint256 _vSignal
575-
) private returns (uint256, uint256) {
574+
)
575+
private
576+
returns (
577+
uint256,
578+
uint256,
579+
uint256
580+
)
581+
{
576582
(uint256 tokens, uint256 withdrawalFees) = curation().burn(_subgraphDeploymentID, _vSignal);
577-
require(
578-
graphToken().transferFrom(_graphAccount, address(this), withdrawalFees),
579-
"GNS: Error reimbursing withdrawal fees"
580-
);
581-
return (tokens, withdrawalFees);
583+
uint256 ownerFee = _ownerFee(withdrawalFees, _graphAccount);
584+
return (tokens, withdrawalFees, ownerFee);
582585
}
583586

584587
/**
@@ -588,7 +591,10 @@ contract GNS is Managed {
588591
* @return Amount the owner must pay by transferring GRT to the GNS
589592
*/
590593
function _ownerFee(uint256 _withdrawalFees, address _owner) private returns (uint256) {
591-
uint256 ownerFee = _withdrawalFees.mul(changeFeePercentage).div(100);
594+
if (ownerFeePercentage == 0) {
595+
return 0;
596+
}
597+
uint256 ownerFee = _withdrawalFees.mul(ownerFeePercentage).div(100);
592598
// Get the owner of the Name to reimburse the withdrawal fee
593599
require(
594600
graphToken().transferFrom(_owner, address(this), ownerFee),

test/gns.test.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,7 @@ describe('GNS', () => {
176176
subgraphToPublish = subgraph0, // Defaults to subgraph created in before()
177177
) => {
178178
// Before stats for the old vSignal curve
179-
const tokensBeforeVSigOldCuration = await getTokensAndVSig(subgraph0.subgraphDeploymentID)
180-
const tokensBeforeOldCuration = tokensBeforeVSigOldCuration[0]
181-
const vSigBeforeOldCuration = tokensBeforeVSigOldCuration[1]
179+
const ownerFee = await gns.ownerFeePercentage()
182180

183181
// Before stats for the name curve
184182
const poolBefore = await gns.nameSignals(graphAccount, subgraphNumber)
@@ -190,11 +188,10 @@ describe('GNS', () => {
190188
subgraphNumber,
191189
nSigBefore,
192190
)
193-
const vSignalBurnEstimate = nSignalToTokensResult[0]
194191
const tokensReceivedEstimate = nSignalToTokensResult[1]
195192

196193
// since in upgrade, owner must refund fees, we need to actually add this back in
197-
const feesToAddBackEstimate = nSignalToTokensResult[2]
194+
const feesToAddBackEstimate = nSignalToTokensResult[2].div(toBN(100 / ownerFee))
198195
const upgradeTokenReturn = tokensReceivedEstimate.add(feesToAddBackEstimate)
199196

200197
// Get the value for new vSignal that should be created on the new curve
@@ -228,12 +225,12 @@ describe('GNS', () => {
228225
subgraphToPublish.subgraphDeploymentID,
229226
)
230227

231-
// Check curation vSignal old was lowered and tokens too
228+
// Check curation vSignal old are set to zero
232229
const tokensVSigOldCuration = await getTokensAndVSig(subgraph0.subgraphDeploymentID)
233230
const tokensAfterOldCuration = tokensVSigOldCuration[0]
234231
const vSigAfterOldCuration = tokensVSigOldCuration[1]
235-
expect(tokensAfterOldCuration).eq(tokensBeforeOldCuration.sub(upgradeTokenReturn))
236-
expect(vSigAfterOldCuration).eq(vSigBeforeOldCuration.sub(vSignalBurnEstimate))
232+
expect(tokensAfterOldCuration).eq(0)
233+
expect(vSigAfterOldCuration).eq(0)
237234

238235
// Check the vSignal of the new curation curve, amd tokens
239236
const tokensVSigNewCuration = await getTokensAndVSig(subgraphToPublish.subgraphDeploymentID)
@@ -260,15 +257,18 @@ describe('GNS', () => {
260257
subgraphNumber0: number,
261258
) => {
262259
const curationBefore = await getTokensAndVSig(subgraph0.subgraphDeploymentID)
260+
const ownerFee = await gns.ownerFeePercentage()
263261
// We can use the whole amount, since in this test suite all vSignal is used to be staked on nSignal
264262
const tokensBefore = curationBefore[0]
265263
const ownerBalanceBefore = await grt.balanceOf(account.address)
264+
const expectedWithdrawalFee = tokensBefore.div(toBN(1000000 / withdrawalPercentage))
265+
const expectedOwnerFee = expectedWithdrawalFee.div(toBN(100 / ownerFee))
266266

267267
const tx = gns.connect(account.signer).deprecateSubgraph(graphAccount, subgraphNumber0)
268268
await expect(tx).emit(gns, 'SubgraphDeprecated').withArgs(subgraph0.graphAccount.address, 0)
269269
await expect(tx)
270270
.emit(gns, 'NameSignalDisabled')
271-
.withArgs(graphAccount, subgraphNumber0, tokensBefore)
271+
.withArgs(graphAccount, subgraphNumber0, tokensBefore.sub(expectedOwnerFee))
272272

273273
const deploymentID = await gns.subgraphs(subgraph0.graphAccount.address, 0)
274274
expect(ethers.constants.HashZero).eq(deploymentID)
@@ -279,11 +279,11 @@ describe('GNS', () => {
279279
expect(poolVSignalAfter.eq(toBN('0')))
280280
// Check that the owner balance decreased by the withdrawal fee
281281
const ownerBalanceAfter = await grt.balanceOf(account.address)
282-
expect(ownerBalanceBefore.sub(tokensBefore.div(toBN(1000000 / withdrawalPercentage)))).eq(
283-
ownerBalanceAfter,
284-
)
282+
expect(ownerBalanceBefore.sub(expectedOwnerFee).eq(ownerBalanceAfter))
285283
// Should be equal since owner pays withdrawal fees
286-
expect(poolAfter.withdrawableGRT).eq(tokensBefore)
284+
expect(poolAfter.withdrawableGRT).eq(
285+
tokensBefore.sub(expectedWithdrawalFee).add(expectedOwnerFee),
286+
)
287287
// Check that deprecated is true
288288
expect(poolAfter.disabled).eq(true)
289289
// Check balance of gns increase by withdrawalFees from owner being added
@@ -901,21 +901,21 @@ describe('GNS', () => {
901901
// we compare 1:1 ratio. Its implied that vSignal is 1 as well (1:1:1)
902902
expect(tokensToDeposit).eq(nSignalCreated)
903903
}
904-
describe('setDeprecateFeePercentage', function () {
904+
describe('setOwnerFeePercentage', function () {
905905
const newValue = 10
906-
it('should set `minimumVSignalStake`', async function () {
906+
it('should set `ownerFeePercentage`', async function () {
907907
// Can set if allowed
908-
await gns.connect(governor.signer).setDeprecateFeePercentage(newValue)
909-
expect(await gns.deprecateFeePercentage()).eq(newValue)
908+
await gns.connect(governor.signer).setOwnerFeePercentage(newValue)
909+
expect(await gns.ownerFeePercentage()).eq(newValue)
910910
})
911911

912-
it('reject set `minimumVSignalStake` if out of bounds', async function () {
913-
const tx = gns.connect(governor.signer).setDeprecateFeePercentage(101)
914-
await expect(tx).revertedWith('Deprecate fee must be 100 or less')
912+
it('reject set `ownerFeePercentage` if out of bounds', async function () {
913+
const tx = gns.connect(governor.signer).setOwnerFeePercentage(101)
914+
await expect(tx).revertedWith('Owner fee must be 100 or less')
915915
})
916916

917-
it('reject set `minimumVSignalStake` if not allowed', async function () {
918-
const tx = gns.connect(me.signer).setDeprecateFeePercentage(newValue)
917+
it('reject set `ownerFeePercentage` if not allowed', async function () {
918+
const tx = gns.connect(me.signer).setOwnerFeePercentage(newValue)
919919
await expect(tx).revertedWith('Caller must be Controller governor')
920920
})
921921
})

0 commit comments

Comments
 (0)