Skip to content

Commit 19516ea

Browse files
committed
Add in owner fee to GNS for upgrade or deprecate
1 parent 009fe5f commit 19516ea

File tree

4 files changed

+55
-14
lines changed

4 files changed

+55
-14
lines changed

cli/commands/protocol/get.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +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' },
4445
// Token
4546
'token-governor': { contract: 'GraphToken', name: 'governor' },
4647
'token-supply': { contract: 'GraphToken', name: 'totalSupply' },

cli/commands/protocol/set.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +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' },
4647
// Token
4748
'token-transfer-governor': { contract: 'GraphToken', name: 'transferOwnership' },
4849
'token-accept-governor': { contract: 'GraphToken', name: 'acceptOwnership' },

contracts/discovery/GNS.sol

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,19 @@ contract GNS is Managed {
3333
// Equates to Connector weight on bancor formula to be CW = 1
3434
uint32 private constant defaultReserveRatio = 1000000;
3535

36+
// In parts per hundred
37+
uint32 public changeFeePercentage = 50;
38+
39+
// Bonding curve formula
40+
address public bondingCurve;
41+
3642
// Amount of nSignal you get with your minimum vSignal stake
3743
uint256 private constant VSIGNAL_PER_MINIMUM_NSIGNAL = 1 ether;
3844

3945
// Minimum amount of vSignal that must be staked to start the curve
4046
// Set to 10**18, as vSignal has 18 decimals
4147
uint256 public minimumVSignalStake = 10**18;
4248

43-
// Bonding curve formula
44-
address public bondingCurve;
45-
4649
// graphAccountID => subgraphNumber => subgraphDeploymentID
4750
// subgraphNumber = A number associated to a graph accounts deployed subgraph. This
4851
// is used to point to a subgraphID (graphAccountID + subgraphNumber)
@@ -203,6 +206,17 @@ contract GNS is Managed {
203206
emit ParameterUpdated("minimumVSignalStake");
204207
}
205208

209+
/**
210+
* @dev Set the change fee percentage. This is used to prevent a subgraph owner to drain all
211+
* the name curators tokens while upgrading or deprecating and is configurable in parts per hundred.
212+
* @param _changeFeePercentage Change fee percentage
213+
*/
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");
218+
}
219+
206220
/**
207221
* @dev Allows a graph account to set a default name
208222
* @param _graphAccount Account that is setting their name
@@ -379,15 +393,13 @@ contract GNS is Managed {
379393
namePool.subgraphDeploymentID,
380394
vSignalOld
381395
);
396+
uint256 ownerFee = _ownerFee(withdrawalFees, _graphAccount);
382397
namePool.vSignal = namePool.vSignal.sub(vSignalOld);
383398
// Update name signals deployment ID to match the subgraphs deployment ID
384399
namePool.subgraphDeploymentID = _newSubgraphDeploymentID;
385400

386401
// nSignal stays constant, but vSignal can change here
387-
uint256 vSignalNew = curation.mint(
388-
namePool.subgraphDeploymentID,
389-
(tokens + withdrawalFees)
390-
);
402+
uint256 vSignalNew = curation.mint(namePool.subgraphDeploymentID, (tokens + ownerFee));
391403
namePool.vSignal = vSignalNew;
392404
emit NameSignalUpgrade(
393405
_graphAccount,
@@ -463,12 +475,8 @@ contract GNS is Managed {
463475
vSignal
464476
);
465477

466-
// Get the owner of the Name to reimburse the withdrawal fee
467-
require(
468-
graphToken().transferFrom(_graphAccount, address(this), withdrawalFees),
469-
"GNS: Error reimbursing withdrawal fees"
470-
);
471-
namePool.withdrawableGRT = tokens + withdrawalFees;
478+
uint256 ownerFee = _ownerFee(withdrawalFees, _graphAccount);
479+
namePool.withdrawableGRT = tokens + ownerFee;
472480
}
473481
// Set the NameCurationPool fields to make it disabled
474482
namePool.disabled = true;
@@ -573,6 +581,22 @@ contract GNS is Managed {
573581
return (tokens, withdrawalFees);
574582
}
575583

584+
/**
585+
* @dev Calculate fee that owner will have to cover for upgrading or deprecating
586+
* @param _owner Subgraph owner
587+
* @param _withdrawalFees Total withdrawal fee for changing subgraphs
588+
* @return Amount the owner must pay by transferring GRT to the GNS
589+
*/
590+
function _ownerFee(uint256 _withdrawalFees, address _owner) private returns (uint256) {
591+
uint256 ownerFee = _withdrawalFees.mul(changeFeePercentage).div(100);
592+
// Get the owner of the Name to reimburse the withdrawal fee
593+
require(
594+
graphToken().transferFrom(_owner, address(this), ownerFee),
595+
"GNS: Error reimbursing withdrawal fees"
596+
);
597+
return ownerFee;
598+
}
599+
576600
/**
577601
* @dev Calculate nSignal to be returned for an amount of tokens
578602
* @param _graphAccount Subgraph owner

test/gns.test.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,6 @@ describe('GNS', () => {
820820
const newValue = toGRT('100')
821821
it('should set `minimumVSignalStake`', async function () {
822822
// Can set if allowed
823-
const newValue = toGRT('100')
824823
await gns.connect(governor.signer).setMinimumVsignal(newValue)
825824
expect(await gns.minimumVSignalStake()).eq(newValue)
826825
})
@@ -902,6 +901,22 @@ describe('GNS', () => {
902901
// we compare 1:1 ratio. Its implied that vSignal is 1 as well (1:1:1)
903902
expect(tokensToDeposit).eq(nSignalCreated)
904903
}
904+
describe('setDeprecateFeePercentage', function () {
905+
const newValue = 10
906+
it('should set `minimumVSignalStake`', async function () {
907+
// Can set if allowed
908+
await gns.connect(governor.signer).setDeprecateFeePercentage(newValue)
909+
expect(await gns.deprecateFeePercentage()).eq(newValue)
910+
})
911+
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')
915+
})
916+
917+
it('reject set `minimumVSignalStake` if not allowed', async function () {
918+
const tx = gns.connect(me.signer).setDeprecateFeePercentage(newValue)
919+
await expect(tx).revertedWith('Caller must be Controller governor')
905920
})
906921
})
907922
})

0 commit comments

Comments
 (0)