-
Notifications
You must be signed in to change notification settings - Fork 47
fix(curation): count curator fees in the network signal total #336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
324db47
2b23558
d104d14
f1b54d9
aafee70
23cb6d7
843d0ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -690,7 +690,49 @@ export function createEpoch(startBlock: i32, epochLength: i32, epochNumber: i32) | |
| export function loadGraphNetwork(): GraphNetwork { | ||
| // Should only be called whenever we are sure a GraphNetwork entity exists. | ||
| // This is only made to centralize the load statements that are everywhere | ||
| return GraphNetwork.load('1')! | ||
| let graphNetwork = GraphNetwork.load('1')! | ||
| countPastCurationFeesInSignal(graphNetwork) | ||
| return graphNetwork | ||
| } | ||
|
Comment on lines
+693
to
+696
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather keep this as it was, instead of adding a graft specific calculation. |
||
|
|
||
| // Versions that left curation fees out of totalTokensSignalled fell short by exactly the fees paid, | ||
| // and a graft inherits that, so add them back once and re-split the total by the value of the GNS | ||
| // contract's shares. Not on L1, which subtracts signal sent to L2 twice, so this would not match. | ||
| function countPastCurationFeesInSignal(graphNetwork: GraphNetwork): void { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this |
||
| if (graphNetwork.curationFeesInSignalTotal) return | ||
| graphNetwork.totalTokensSignalled = graphNetwork.totalTokensSignalled.plus( | ||
| graphNetwork.totalCuratorQueryFees, | ||
| ) | ||
| graphNetwork.curationFeesInSignalTotal = true | ||
| if (!addresses.isL1) splitSignalByGnsShareValue(graphNetwork) | ||
| // Save now so later loads in this block see the flag instead of walking every GNS signal again | ||
| graphNetwork.save() | ||
| } | ||
|
|
||
| function splitSignalByGnsShareValue(graphNetwork: GraphNetwork): void { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this |
||
| let autoMigrate = BigDecimal.fromString('0') | ||
| let gnsCurator = Curator.load(graphNetwork.gns.toHexString()) | ||
| if (gnsCurator != null) { | ||
| let gnsSignals = gnsCurator.signals.load() | ||
| for (let i = 0; i < gnsSignals.length; i++) { | ||
| let gnsSignal = gnsSignals[i] | ||
| if (gnsSignal.signal.isZero()) continue | ||
| let deployment = SubgraphDeployment.load(gnsSignal.subgraphDeployment)! | ||
| if (deployment.signalAmount.isZero()) continue | ||
| autoMigrate = autoMigrate | ||
| .plus( | ||
| gnsSignal.signal | ||
| .toBigDecimal() | ||
| .times(deployment.signalledTokens.toBigDecimal()) | ||
| .div(deployment.signalAmount.toBigDecimal()), | ||
| ) | ||
| .truncate(18) | ||
| } | ||
| } | ||
| graphNetwork.totalTokensSignalledAutoMigrate = autoMigrate | ||
| graphNetwork.totalTokensSignalledDirectly = graphNetwork.totalTokensSignalled | ||
| .toBigDecimal() | ||
| .minus(autoMigrate) | ||
| } | ||
|
|
||
| export function createOrLoadGraphNetwork( | ||
|
|
@@ -756,6 +798,7 @@ export function createOrLoadGraphNetwork( | |
| graphNetwork.totalTokensSignalled = BigInt.fromI32(0) | ||
| graphNetwork.totalTokensSignalledAutoMigrate = BigDecimal.fromString('0') | ||
| graphNetwork.totalTokensSignalledDirectly = BigDecimal.fromString('0') | ||
| graphNetwork.curationFeesInSignalTotal = true | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this |
||
|
|
||
| graphNetwork.totalQueryFees = BigInt.fromI32(0) | ||
| graphNetwork.totalIndexerQueryFeesCollected = BigInt.fromI32(0) | ||
|
|
@@ -839,6 +882,7 @@ export function createOrLoadGraphNetwork( | |
|
|
||
| graphNetwork.save() | ||
| } | ||
| countPastCurationFeesInSignal(graphNetwork) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this |
||
|
|
||
| if (!addresses.isL1) { | ||
| graphNetwork.currentL1BlockNumber = getL1BlockNumber() | ||
|
|
@@ -983,9 +1027,9 @@ function createGraphAccountName( | |
| graphAccountName.graphAccount = graphAccount | ||
| graphAccountName.save() | ||
| // check that this name is not already used by another graph account (changing ownership) | ||
| // If so, remove the old owner, and set the new one | ||
| // If so, move the name from its former owner to the new one | ||
| } else if (graphAccountName.graphAccount != graphAccount) { | ||
| // Only update the old graph account if it exists | ||
| // Only update the former owner's graph account if it exists | ||
| if (graphAccountName.graphAccount != null) { | ||
| // Set defaultDisplayName to null if they lost ownership of this name | ||
| let oldGraphAccount = GraphAccount.load(graphAccountName.graphAccount!)! | ||
|
|
@@ -1242,13 +1286,8 @@ export function calculateCapacitiesLegacy(indexer: Indexer): Indexer { | |
| } | ||
|
|
||
| export function calculatePricePerShare(deployment: SubgraphDeployment): BigDecimal { | ||
| // TODO check why there's a deviation from the values of the bancor formula | ||
| // Ideally this would be a 1 to 1 recreation of the share sell formula, but due to | ||
| // implementation issues for that formula on AssemblyScript (mainly BigDecimal missing pow implementation) | ||
| // I decided to use an approximation derived from testing. | ||
|
|
||
| // This value could be wrong unfortunately, so we should ideally find a workaround later | ||
| // to implement the actual sell share formula for 1 share. | ||
| // TODO: implement the bancor sell formula for 1 share exactly. This is an approximation found | ||
| // by testing, because AssemblyScript's BigDecimal has no pow, so it can deviate from the formula. | ||
|
|
||
| // reserve ratio multiplier = MAX_WEIGHT / reserveRatio = 1M (ppm) / reserveRatio | ||
| // HOTFIX for now, if deployment.reserveRatio -> 0, use a known previous default | ||
|
|
@@ -1264,42 +1303,6 @@ export function calculatePricePerShare(deployment: SubgraphDeployment): BigDecim | |
| return pricePerShare | ||
| } | ||
|
|
||
| // export function createOrLoadNetwork(id: string): Network { | ||
| // let network = Network.load(id) | ||
| // if (network == null) { | ||
| // network = new Network(id) | ||
|
|
||
| // network.save() | ||
| // } | ||
| // return network as Network | ||
| // } | ||
|
|
||
| // export function createOrLoadSubgraphCategory(id: string): SubgraphCategory { | ||
| // let category = SubgraphCategory.load(id) | ||
| // if (category == null) { | ||
| // category = new SubgraphCategory(id) | ||
|
|
||
| // category.save() | ||
| // } | ||
| // return category as SubgraphCategory | ||
| // } | ||
|
|
||
| // export function createOrLoadSubgraphCategoryRelation( | ||
| // categoryId: string, | ||
| // subgraphMetadataId: string, | ||
| // ): SubgraphCategoryRelation { | ||
| // let id = joinID([categoryId, subgraphMetadataId]) | ||
| // let relation = SubgraphCategoryRelation.load(id) | ||
| // if (relation == null) { | ||
| // relation = new SubgraphCategoryRelation(id) | ||
| // relation.metadata = subgraphMetadataId | ||
| // relation.category = categoryId | ||
|
|
||
| // relation.save() | ||
| // } | ||
| // return relation as SubgraphCategoryRelation | ||
| // } | ||
|
|
||
| export function updateCurrentDeploymentLinks( | ||
| oldDeployment: SubgraphDeployment | null, | ||
| newDeployment: SubgraphDeployment | null, | ||
|
|
@@ -1342,6 +1345,31 @@ export function updateCurrentDeploymentLinks( | |
| } | ||
| } | ||
|
|
||
| // Curation fees raise a pool's signalled tokens without minting signal, so count them here. | ||
| // Every share gains the same value: the GNS contract's shares take their part as | ||
| // auto-migrating signal and the rest counts as signalled directly. | ||
| export function addCurationFeesToNetworkSignal( | ||
| graphNetwork: GraphNetwork, | ||
| deployment: SubgraphDeployment, | ||
| fees: BigInt, | ||
| ): void { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't exactly remember if this is still an issue with graph node, but at some point in order for graph-node to properly update your entities when modifying them in a separate function, you had to return the "new" updated entity, and reassign them to your variable. I'm like 95% sure this doesn't happen anymore, but potentially worth checking. I'll explain in the next line. |
||
| graphNetwork.totalTokensSignalled = graphNetwork.totalTokensSignalled.plus(fees) | ||
| let toGns = BigDecimal.fromString('0') | ||
| let gnsSignal = Signal.load(joinID([graphNetwork.gns.toHexString(), deployment.id])) | ||
| if (gnsSignal != null && !deployment.signalAmount.isZero()) { | ||
| toGns = fees | ||
| .toBigDecimal() | ||
| .times(gnsSignal.signal.toBigDecimal()) | ||
| .div(deployment.signalAmount.toBigDecimal()) | ||
| } | ||
| graphNetwork.totalTokensSignalledAutoMigrate = graphNetwork.totalTokensSignalledAutoMigrate | ||
| .plus(toGns) | ||
| .truncate(18) | ||
| graphNetwork.totalTokensSignalledDirectly = graphNetwork.totalTokensSignalledDirectly | ||
| .plus(fees.toBigDecimal().minus(toGns)) | ||
| .truncate(18) | ||
| } | ||
|
|
||
| export function batchUpdateSubgraphSignalledTokens(deployment: SubgraphDeployment): void { | ||
| for (let i = 0; i < deployment.subgraphCount; i++) { | ||
| let id = deployment.id.concat('-').concat(BigInt.fromI32(i).toString()) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| import { BigInt, BigDecimal, Bytes } from '@graphprotocol/graph-ts' | ||
| import { BigInt, BigDecimal } from '@graphprotocol/graph-ts' | ||
| import { | ||
| StakeDeposited, | ||
| StakeWithdrawn, | ||
|
|
@@ -28,7 +28,6 @@ import { | |
| GraphAccount, | ||
| Delegator, | ||
| DelegatedStake, | ||
| IndexerQueryFeePaymentAggregation, | ||
| } from '../types/schema' | ||
|
|
||
| import { | ||
|
|
@@ -43,6 +42,7 @@ import { | |
| updateDelegationExchangeRate, | ||
| calculatePricePerShare, | ||
| batchUpdateSubgraphSignalledTokens, | ||
| addCurationFeesToNetworkSignal, | ||
| createOrLoadGraphNetwork, | ||
| calculateCapacities, | ||
| createOrLoadIndexerQueryFeePaymentAggregation, | ||
|
|
@@ -499,6 +499,7 @@ export function handleAllocationCollected(event: AllocationCollected): void { | |
| graphNetwork.totalCuratorQueryFees = graphNetwork.totalCuratorQueryFees.plus( | ||
| event.params.curationFees, | ||
| ) | ||
| addCurationFeesToNetworkSignal(graphNetwork, deployment, event.params.curationFees) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, at some point, you used to need to do this: Unsure if that's still a thing, but worth mentioning. |
||
| graphNetwork.totalTaxedQueryFees = graphNetwork.totalTaxedQueryFees.plus(taxedFees) | ||
| graphNetwork.totalUnclaimedQueryFeeRebates = graphNetwork.totalUnclaimedQueryFeeRebates.plus( | ||
| event.params.rebateFees, | ||
|
|
@@ -804,6 +805,7 @@ export function handleRebateCollected(event: RebateCollected): void { | |
| graphNetwork.totalCuratorQueryFees = graphNetwork.totalCuratorQueryFees.plus( | ||
| event.params.curationFees, | ||
| ) | ||
| addCurationFeesToNetworkSignal(graphNetwork, deployment, event.params.curationFees) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as the last comment |
||
| graphNetwork.totalTaxedQueryFees = graphNetwork.totalTaxedQueryFees.plus(event.params.protocolTax) | ||
| graphNetwork.totalUnclaimedQueryFeeRebates = graphNetwork.totalUnclaimedQueryFeeRebates.plus( | ||
| event.params.queryFees, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| import { BigDecimal, BigInt, ByteArray, Bytes, crypto, ethereum, log } from "@graphprotocol/graph-ts" | ||
| import { AllocationClosed, AllocationCreated, AllocationResized, CurationCutSet, DelegationRatioSet, IndexingRewardsCollected, MaxPOIStalenessSet, POIPresented, ProvisionTokensRangeSet, QueryFeesCollected, RewardsDestinationSet, ServiceProviderRegistered, StakeToFeesRatioSet, ThawingPeriodRangeSet, VerifierCutRangeSet } from "../types/SubgraphService/SubgraphService" | ||
| import { batchUpdateSubgraphSignalledTokens, calculatePricePerShare, createOrLoadDataService, createOrLoadGraphNetwork, createOrLoadEpoch,createOrLoadIndexerQueryFeePaymentAggregation, createOrLoadPaymentSource, createOrLoadProvision, createOrLoadSubgraphDeployment, joinID, updateDelegationExchangeRate, calculateCapacities, loadGraphNetwork } from "./helpers/helpers" | ||
| import { addCurationFeesToNetworkSignal, batchUpdateSubgraphSignalledTokens, calculatePricePerShare, createOrLoadDataService, createOrLoadGraphNetwork, createOrLoadEpoch,createOrLoadIndexerQueryFeePaymentAggregation, createOrLoadPaymentSource, createOrLoadProvision, createOrLoadSubgraphDeployment, joinID, calculateCapacities, loadGraphNetwork } from "./helpers/helpers" | ||
| import { Allocation, Indexer, PoiSubmission, SubgraphDeployment } from "../types/schema" | ||
| import { addresses } from "../../config/addresses" | ||
| import { tuplePrefixBytes } from "./helpers/decoder" | ||
|
|
@@ -510,6 +510,7 @@ export function handleQueryFeesCollected(event: QueryFeesCollected): void { | |
| graphNetwork.totalCuratorQueryFees = graphNetwork.totalCuratorQueryFees.plus( | ||
| event.params.tokensCurators, | ||
| ) | ||
| addCurationFeesToNetworkSignal(graphNetwork, deployment, event.params.tokensCurators) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as the last comment |
||
| graphNetwork.totalIndexerQueryFeeRebates = graphNetwork.totalIndexerQueryFeeRebates.plus( | ||
| indexerQueryFees, | ||
| ) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed anymore